mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
Fix contextual types for maybe-async callbacks (#37205)
* Fix contextual types for maybe-async callbacks * Remove comment
This commit is contained in:
parent
9cd4b070ab
commit
2f0cc51fee
@ -21810,7 +21810,7 @@ namespace ts {
|
||||
const contextualReturnType = getContextualReturnType(func);
|
||||
if (contextualReturnType) {
|
||||
if (functionFlags & FunctionFlags.Async) { // Async function
|
||||
const contextualAwaitedType = getAwaitedTypeOfPromise(contextualReturnType);
|
||||
const contextualAwaitedType = mapType(contextualReturnType, getAwaitedTypeOfPromise);
|
||||
return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]);
|
||||
}
|
||||
return contextualReturnType; // Regular function
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
//// [asyncFunctionContextuallyTypedReturns.ts]
|
||||
declare function f(cb: (v: boolean) => [0] | PromiseLike<[0]>): void;
|
||||
f(v => v ? [0] : Promise.reject());
|
||||
f(async v => v ? [0] : Promise.reject());
|
||||
|
||||
declare function g(cb: (v: boolean) => "contextuallyTypable" | PromiseLike<"contextuallyTypable">): void;
|
||||
g(v => v ? "contextuallyTypable" : Promise.reject());
|
||||
g(async v => v ? "contextuallyTypable" : Promise.reject());
|
||||
|
||||
type MyCallback = (thing: string) => void;
|
||||
declare function h(cb: (v: boolean) => MyCallback | PromiseLike<MyCallback>): void;
|
||||
h(v => v ? (abc) => { } : Promise.reject());
|
||||
h(async v => v ? (def) => { } : Promise.reject());
|
||||
|
||||
|
||||
//// [asyncFunctionContextuallyTypedReturns.js]
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
f(v => v ? [0] : Promise.reject());
|
||||
f((v) => __awaiter(void 0, void 0, void 0, function* () { return v ? [0] : Promise.reject(); }));
|
||||
g(v => v ? "contextuallyTypable" : Promise.reject());
|
||||
g((v) => __awaiter(void 0, void 0, void 0, function* () { return v ? "contextuallyTypable" : Promise.reject(); }));
|
||||
h(v => v ? (abc) => { } : Promise.reject());
|
||||
h((v) => __awaiter(void 0, void 0, void 0, function* () { return v ? (def) => { } : Promise.reject(); }));
|
||||
@ -0,0 +1,75 @@
|
||||
=== tests/cases/compiler/asyncFunctionContextuallyTypedReturns.ts ===
|
||||
declare function f(cb: (v: boolean) => [0] | PromiseLike<[0]>): void;
|
||||
>f : Symbol(f, Decl(asyncFunctionContextuallyTypedReturns.ts, 0, 0))
|
||||
>cb : Symbol(cb, Decl(asyncFunctionContextuallyTypedReturns.ts, 0, 19))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 0, 24))
|
||||
>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
f(v => v ? [0] : Promise.reject());
|
||||
>f : Symbol(f, Decl(asyncFunctionContextuallyTypedReturns.ts, 0, 0))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 1, 2))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 1, 2))
|
||||
>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
|
||||
>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
|
||||
f(async v => v ? [0] : Promise.reject());
|
||||
>f : Symbol(f, Decl(asyncFunctionContextuallyTypedReturns.ts, 0, 0))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 2, 7))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 2, 7))
|
||||
>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
|
||||
>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
|
||||
declare function g(cb: (v: boolean) => "contextuallyTypable" | PromiseLike<"contextuallyTypable">): void;
|
||||
>g : Symbol(g, Decl(asyncFunctionContextuallyTypedReturns.ts, 2, 41))
|
||||
>cb : Symbol(cb, Decl(asyncFunctionContextuallyTypedReturns.ts, 4, 19))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 4, 24))
|
||||
>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
g(v => v ? "contextuallyTypable" : Promise.reject());
|
||||
>g : Symbol(g, Decl(asyncFunctionContextuallyTypedReturns.ts, 2, 41))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 5, 2))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 5, 2))
|
||||
>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
|
||||
>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
|
||||
g(async v => v ? "contextuallyTypable" : Promise.reject());
|
||||
>g : Symbol(g, Decl(asyncFunctionContextuallyTypedReturns.ts, 2, 41))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 6, 7))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 6, 7))
|
||||
>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
|
||||
>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
|
||||
type MyCallback = (thing: string) => void;
|
||||
>MyCallback : Symbol(MyCallback, Decl(asyncFunctionContextuallyTypedReturns.ts, 6, 59))
|
||||
>thing : Symbol(thing, Decl(asyncFunctionContextuallyTypedReturns.ts, 8, 19))
|
||||
|
||||
declare function h(cb: (v: boolean) => MyCallback | PromiseLike<MyCallback>): void;
|
||||
>h : Symbol(h, Decl(asyncFunctionContextuallyTypedReturns.ts, 8, 42))
|
||||
>cb : Symbol(cb, Decl(asyncFunctionContextuallyTypedReturns.ts, 9, 19))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 9, 24))
|
||||
>MyCallback : Symbol(MyCallback, Decl(asyncFunctionContextuallyTypedReturns.ts, 6, 59))
|
||||
>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --))
|
||||
>MyCallback : Symbol(MyCallback, Decl(asyncFunctionContextuallyTypedReturns.ts, 6, 59))
|
||||
|
||||
h(v => v ? (abc) => { } : Promise.reject());
|
||||
>h : Symbol(h, Decl(asyncFunctionContextuallyTypedReturns.ts, 8, 42))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 10, 2))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 10, 2))
|
||||
>abc : Symbol(abc, Decl(asyncFunctionContextuallyTypedReturns.ts, 10, 12))
|
||||
>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
|
||||
>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
|
||||
h(async v => v ? (def) => { } : Promise.reject());
|
||||
>h : Symbol(h, Decl(asyncFunctionContextuallyTypedReturns.ts, 8, 42))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 11, 7))
|
||||
>v : Symbol(v, Decl(asyncFunctionContextuallyTypedReturns.ts, 11, 7))
|
||||
>def : Symbol(def, Decl(asyncFunctionContextuallyTypedReturns.ts, 11, 18))
|
||||
>Promise.reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
|
||||
>reject : Symbol(PromiseConstructor.reject, Decl(lib.es2015.promise.d.ts, --, --))
|
||||
|
||||
@ -0,0 +1,102 @@
|
||||
=== tests/cases/compiler/asyncFunctionContextuallyTypedReturns.ts ===
|
||||
declare function f(cb: (v: boolean) => [0] | PromiseLike<[0]>): void;
|
||||
>f : (cb: (v: boolean) => [0] | PromiseLike<[0]>) => void
|
||||
>cb : (v: boolean) => [0] | PromiseLike<[0]>
|
||||
>v : boolean
|
||||
|
||||
f(v => v ? [0] : Promise.reject());
|
||||
>f(v => v ? [0] : Promise.reject()) : void
|
||||
>f : (cb: (v: boolean) => [0] | PromiseLike<[0]>) => void
|
||||
>v => v ? [0] : Promise.reject() : (v: boolean) => [0] | Promise<[0]>
|
||||
>v : boolean
|
||||
>v ? [0] : Promise.reject() : [0] | Promise<[0]>
|
||||
>v : boolean
|
||||
>[0] : [0]
|
||||
>0 : 0
|
||||
>Promise.reject() : Promise<[0]>
|
||||
>Promise.reject : <T = never>(reason?: any) => Promise<T>
|
||||
>Promise : PromiseConstructor
|
||||
>reject : <T = never>(reason?: any) => Promise<T>
|
||||
|
||||
f(async v => v ? [0] : Promise.reject());
|
||||
>f(async v => v ? [0] : Promise.reject()) : void
|
||||
>f : (cb: (v: boolean) => [0] | PromiseLike<[0]>) => void
|
||||
>async v => v ? [0] : Promise.reject() : (v: boolean) => Promise<[0] | [0]>
|
||||
>v : boolean
|
||||
>v ? [0] : Promise.reject() : [0] | Promise<[0]>
|
||||
>v : boolean
|
||||
>[0] : [0]
|
||||
>0 : 0
|
||||
>Promise.reject() : Promise<[0]>
|
||||
>Promise.reject : <T = never>(reason?: any) => Promise<T>
|
||||
>Promise : PromiseConstructor
|
||||
>reject : <T = never>(reason?: any) => Promise<T>
|
||||
|
||||
declare function g(cb: (v: boolean) => "contextuallyTypable" | PromiseLike<"contextuallyTypable">): void;
|
||||
>g : (cb: (v: boolean) => "contextuallyTypable" | PromiseLike<"contextuallyTypable">) => void
|
||||
>cb : (v: boolean) => "contextuallyTypable" | PromiseLike<"contextuallyTypable">
|
||||
>v : boolean
|
||||
|
||||
g(v => v ? "contextuallyTypable" : Promise.reject());
|
||||
>g(v => v ? "contextuallyTypable" : Promise.reject()) : void
|
||||
>g : (cb: (v: boolean) => "contextuallyTypable" | PromiseLike<"contextuallyTypable">) => void
|
||||
>v => v ? "contextuallyTypable" : Promise.reject() : (v: boolean) => "contextuallyTypable" | Promise<"contextuallyTypable">
|
||||
>v : boolean
|
||||
>v ? "contextuallyTypable" : Promise.reject() : "contextuallyTypable" | Promise<"contextuallyTypable">
|
||||
>v : boolean
|
||||
>"contextuallyTypable" : "contextuallyTypable"
|
||||
>Promise.reject() : Promise<"contextuallyTypable">
|
||||
>Promise.reject : <T = never>(reason?: any) => Promise<T>
|
||||
>Promise : PromiseConstructor
|
||||
>reject : <T = never>(reason?: any) => Promise<T>
|
||||
|
||||
g(async v => v ? "contextuallyTypable" : Promise.reject());
|
||||
>g(async v => v ? "contextuallyTypable" : Promise.reject()) : void
|
||||
>g : (cb: (v: boolean) => "contextuallyTypable" | PromiseLike<"contextuallyTypable">) => void
|
||||
>async v => v ? "contextuallyTypable" : Promise.reject() : (v: boolean) => Promise<"contextuallyTypable">
|
||||
>v : boolean
|
||||
>v ? "contextuallyTypable" : Promise.reject() : "contextuallyTypable" | Promise<"contextuallyTypable">
|
||||
>v : boolean
|
||||
>"contextuallyTypable" : "contextuallyTypable"
|
||||
>Promise.reject() : Promise<"contextuallyTypable">
|
||||
>Promise.reject : <T = never>(reason?: any) => Promise<T>
|
||||
>Promise : PromiseConstructor
|
||||
>reject : <T = never>(reason?: any) => Promise<T>
|
||||
|
||||
type MyCallback = (thing: string) => void;
|
||||
>MyCallback : MyCallback
|
||||
>thing : string
|
||||
|
||||
declare function h(cb: (v: boolean) => MyCallback | PromiseLike<MyCallback>): void;
|
||||
>h : (cb: (v: boolean) => MyCallback | PromiseLike<MyCallback>) => void
|
||||
>cb : (v: boolean) => MyCallback | PromiseLike<MyCallback>
|
||||
>v : boolean
|
||||
|
||||
h(v => v ? (abc) => { } : Promise.reject());
|
||||
>h(v => v ? (abc) => { } : Promise.reject()) : void
|
||||
>h : (cb: (v: boolean) => MyCallback | PromiseLike<MyCallback>) => void
|
||||
>v => v ? (abc) => { } : Promise.reject() : (v: boolean) => ((abc: string) => void) | Promise<MyCallback>
|
||||
>v : boolean
|
||||
>v ? (abc) => { } : Promise.reject() : ((abc: string) => void) | Promise<MyCallback>
|
||||
>v : boolean
|
||||
>(abc) => { } : (abc: string) => void
|
||||
>abc : string
|
||||
>Promise.reject() : Promise<MyCallback>
|
||||
>Promise.reject : <T = never>(reason?: any) => Promise<T>
|
||||
>Promise : PromiseConstructor
|
||||
>reject : <T = never>(reason?: any) => Promise<T>
|
||||
|
||||
h(async v => v ? (def) => { } : Promise.reject());
|
||||
>h(async v => v ? (def) => { } : Promise.reject()) : void
|
||||
>h : (cb: (v: boolean) => MyCallback | PromiseLike<MyCallback>) => void
|
||||
>async v => v ? (def) => { } : Promise.reject() : (v: boolean) => Promise<MyCallback | ((def: string) => void)>
|
||||
>v : boolean
|
||||
>v ? (def) => { } : Promise.reject() : Promise<MyCallback> | ((def: string) => void)
|
||||
>v : boolean
|
||||
>(def) => { } : (def: string) => void
|
||||
>def : string
|
||||
>Promise.reject() : Promise<MyCallback>
|
||||
>Promise.reject : <T = never>(reason?: any) => Promise<T>
|
||||
>Promise : PromiseConstructor
|
||||
>reject : <T = never>(reason?: any) => Promise<T>
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
// @target: es6
|
||||
// @strict: true
|
||||
declare function f(cb: (v: boolean) => [0] | PromiseLike<[0]>): void;
|
||||
f(v => v ? [0] : Promise.reject());
|
||||
f(async v => v ? [0] : Promise.reject());
|
||||
|
||||
declare function g(cb: (v: boolean) => "contextuallyTypable" | PromiseLike<"contextuallyTypable">): void;
|
||||
g(v => v ? "contextuallyTypable" : Promise.reject());
|
||||
g(async v => v ? "contextuallyTypable" : Promise.reject());
|
||||
|
||||
type MyCallback = (thing: string) => void;
|
||||
declare function h(cb: (v: boolean) => MyCallback | PromiseLike<MyCallback>): void;
|
||||
h(v => v ? (abc) => { } : Promise.reject());
|
||||
h(async v => v ? (def) => { } : Promise.reject());
|
||||
Loading…
x
Reference in New Issue
Block a user