Skip to content

Commit e5a509e

Browse files
committed
Better typings for Promise.then(), like #31117
1 parent ba5e86f commit e5a509e

File tree

56 files changed

+942
-980
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+942
-980
lines changed

src/lib/es5.d.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,7 @@ interface PromiseLike<T> {
13871387
* @param onrejected The callback to execute when the Promise is rejected.
13881388
* @returns A Promise for the completion of which ever callback is executed.
13891389
*/
1390-
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
1390+
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1) | undefined | null, onrejected?: ((reason: any) => TResult2) | undefined | null): PromiseLike<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>;
13911391
}
13921392

13931393
/**
@@ -1400,14 +1400,14 @@ interface Promise<T> {
14001400
* @param onrejected The callback to execute when the Promise is rejected.
14011401
* @returns A Promise for the completion of which ever callback is executed.
14021402
*/
1403-
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
1403+
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1) | undefined | null, onrejected?: ((reason: any) => TResult2) | undefined | null): Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>;
14041404

14051405
/**
14061406
* Attaches a callback for only the rejection of the Promise.
14071407
* @param onrejected The callback to execute when the Promise is rejected.
14081408
* @returns A Promise for the completion of the callback.
14091409
*/
1410-
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
1410+
catch<TResult = never>(onrejected?: ((reason: any) => TResult) | undefined | null): Promise<T | (TResult extends PromiseLike<infer UResult> ? UResult : TResult)>;
14111411
}
14121412

14131413
interface ArrayLike<T> {

tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
77
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
88
Construct signature return types 'Thenable' and 'PromiseLike<T>' are incompatible.
99
The types returned by 'then(...)' are incompatible between these types.
10-
Type 'void' is not assignable to type 'PromiseLike<TResult1 | TResult2>'.
10+
Type 'void' is not assignable to type 'PromiseLike<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>'.
1111
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(17,16): error TS1058: The return type of an async function must either be a valid promise or must not contain a callable 'then' member.
1212
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(23,25): error TS1320: Type of 'await' operand must either be a valid promise or must not contain a callable 'then' member.
1313

@@ -39,7 +39,7 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
3939
!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
4040
!!! error TS1055: Construct signature return types 'Thenable' and 'PromiseLike<T>' are incompatible.
4141
!!! error TS1055: The types returned by 'then(...)' are incompatible between these types.
42-
!!! error TS1055: Type 'void' is not assignable to type 'PromiseLike<TResult1 | TResult2>'.
42+
!!! error TS1055: Type 'void' is not assignable to type 'PromiseLike<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>'.
4343
async function fn7() { return; } // valid: Promise<void>
4444
async function fn8() { return 1; } // valid: Promise<number>
4545
async function fn9() { return null; } // valid: Promise<any>

tests/baselines/reference/declarationEmitExportAliasVisibiilityMarking.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ export let lazyCard = () => import('./Card').then(a => a.default);
2828
>lazyCard : () => Promise<(suit: import("tests/cases/compiler/Types").Suit, rank: import("tests/cases/compiler/Types").Rank) => { suit: import("tests/cases/compiler/Types").Suit; rank: import("tests/cases/compiler/Types").Rank; }>
2929
>() => import('./Card').then(a => a.default) : () => Promise<(suit: import("tests/cases/compiler/Types").Suit, rank: import("tests/cases/compiler/Types").Rank) => { suit: import("tests/cases/compiler/Types").Suit; rank: import("tests/cases/compiler/Types").Rank; }>
3030
>import('./Card').then(a => a.default) : Promise<(suit: import("tests/cases/compiler/Types").Suit, rank: import("tests/cases/compiler/Types").Rank) => { suit: import("tests/cases/compiler/Types").Suit; rank: import("tests/cases/compiler/Types").Rank; }>
31-
>import('./Card').then : <TResult1 = typeof import("tests/cases/compiler/Card"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/compiler/Card")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
31+
>import('./Card').then : <TResult1 = typeof import("tests/cases/compiler/Card"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/compiler/Card")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
3232
>import('./Card') : Promise<typeof import("tests/cases/compiler/Card")>
3333
>'./Card' : "./Card"
34-
>then : <TResult1 = typeof import("tests/cases/compiler/Card"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/compiler/Card")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
34+
>then : <TResult1 = typeof import("tests/cases/compiler/Card"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/compiler/Card")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
3535
>a => a.default : (a: typeof import("tests/cases/compiler/Card")) => (suit: import("tests/cases/compiler/Types").Suit, rank: import("tests/cases/compiler/Types").Rank) => { suit: import("tests/cases/compiler/Types").Suit; rank: import("tests/cases/compiler/Types").Rank; }
3636
>a : typeof import("tests/cases/compiler/Card")
3737
>a.default : (suit: import("tests/cases/compiler/Types").Suit, rank: import("tests/cases/compiler/Types").Rank) => { suit: import("tests/cases/compiler/Types").Suit; rank: import("tests/cases/compiler/Types").Rank; }

tests/baselines/reference/esModuleInteropImportCall.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ export = foo;
99
=== tests/cases/compiler/index.ts ===
1010
import("./foo").then(f => {
1111
>import("./foo").then(f => { f.default;}) : Promise<void>
12-
>import("./foo").then : <TResult1 = { default: () => void; }, TResult2 = never>(onfulfilled?: (value: { default: () => void; }) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
12+
>import("./foo").then : <TResult1 = { default: () => void; }, TResult2 = never>(onfulfilled?: (value: { default: () => void; }) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
1313
>import("./foo") : Promise<{ default: () => void; }>
1414
>"./foo" : "./foo"
15-
>then : <TResult1 = { default: () => void; }, TResult2 = never>(onfulfilled?: (value: { default: () => void; }) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
15+
>then : <TResult1 = { default: () => void; }, TResult2 = never>(onfulfilled?: (value: { default: () => void; }) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
1616
>f => { f.default;} : (f: { default: () => void; }) => void
1717
>f : { default: () => void; }
1818

tests/baselines/reference/genericFunctionInference1.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -842,9 +842,9 @@ const promise = Promise.resolve(1);
842842

843843
promise.then(
844844
>promise.then( pipe( x => x + 1, x => x * 2, ),) : Promise<number>
845-
>promise.then : <TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>
845+
>promise.then : <TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
846846
>promise : Promise<number>
847-
>then : <TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>
847+
>then : <TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
848848

849849
pipe(
850850
>pipe( x => x + 1, x => x * 2, ) : (x: number) => number

tests/baselines/reference/importCallExpression1ESNext.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ var p1 = import("./0");
1515

1616
p1.then(zero => {
1717
>p1.then(zero => { return zero.foo();}) : Promise<string>
18-
>p1.then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
18+
>p1.then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
1919
>p1 : Promise<typeof import("tests/cases/conformance/dynamicImport/0")>
20-
>then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
20+
>then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
2121
>zero => { return zero.foo();} : (zero: typeof import("tests/cases/conformance/dynamicImport/0")) => string
2222
>zero : typeof import("tests/cases/conformance/dynamicImport/0")
2323

tests/baselines/reference/importCallExpression2ESNext.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ function foo(x: Promise<any>) {
1414

1515
x.then(value => {
1616
>x.then(value => { let b = new value.B(); b.print(); }) : Promise<void>
17-
>x.then : <TResult1 = any, TResult2 = never>(onfulfilled?: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
17+
>x.then : <TResult1 = any, TResult2 = never>(onfulfilled?: (value: any) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
1818
>x : Promise<any>
19-
>then : <TResult1 = any, TResult2 = never>(onfulfilled?: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
19+
>then : <TResult1 = any, TResult2 = never>(onfulfilled?: (value: any) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
2020
>value => { let b = new value.B(); b.print(); } : (value: any) => void
2121
>value : any
2222

tests/baselines/reference/importCallExpression4ESNext.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ class C {
3838

3939
this.myModule.then(Zero => {
4040
>this.myModule.then(Zero => { console.log(Zero.foo()); }, async err => { console.log(err); let one = await import("./1"); console.log(one.backup()); }) : Promise<void>
41-
>this.myModule.then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
41+
>this.myModule.then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
4242
>this.myModule : Promise<typeof import("tests/cases/conformance/dynamicImport/0")>
4343
>this : this
4444
>myModule : Promise<typeof import("tests/cases/conformance/dynamicImport/0")>
45-
>then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
45+
>then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
4646
>Zero => { console.log(Zero.foo()); } : (Zero: typeof import("tests/cases/conformance/dynamicImport/0")) => void
4747
>Zero : typeof import("tests/cases/conformance/dynamicImport/0")
4848

tests/baselines/reference/importCallExpressionES5AMD.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ var p1 = import("./0");
1515

1616
p1.then(zero => {
1717
>p1.then(zero => { return zero.foo();}) : Promise<string>
18-
>p1.then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
18+
>p1.then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
1919
>p1 : Promise<typeof import("tests/cases/conformance/dynamicImport/0")>
20-
>then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
20+
>then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
2121
>zero => { return zero.foo();} : (zero: typeof import("tests/cases/conformance/dynamicImport/0")) => string
2222
>zero : typeof import("tests/cases/conformance/dynamicImport/0")
2323

tests/baselines/reference/importCallExpressionES5CJS.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ var p1 = import("./0");
1515

1616
p1.then(zero => {
1717
>p1.then(zero => { return zero.foo();}) : Promise<string>
18-
>p1.then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
18+
>p1.then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
1919
>p1 : Promise<typeof import("tests/cases/conformance/dynamicImport/0")>
20-
>then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
20+
>then : <TResult1 = typeof import("tests/cases/conformance/dynamicImport/0"), TResult2 = never>(onfulfilled?: (value: typeof import("tests/cases/conformance/dynamicImport/0")) => TResult1, onrejected?: (reason: any) => TResult2) => Promise<(TResult1 extends PromiseLike<infer UResult1> ? UResult1 : TResult1) | (TResult2 extends PromiseLike<infer UResult2> ? UResult2 : TResult2)>
2121
>zero => { return zero.foo();} : (zero: typeof import("tests/cases/conformance/dynamicImport/0")) => string
2222
>zero : typeof import("tests/cases/conformance/dynamicImport/0")
2323

0 commit comments

Comments
 (0)