Skip to content

Commit dd6c87e

Browse files
committed
Merge pull request microsoft#3058 from Microsoft/promiseVoidErrorCallback
Fix typing for Promises so that a void error callback doesn't mess up inference
2 parents 3d0daef + 498f315 commit dd6c87e

File tree

5 files changed

+237
-0
lines changed

5 files changed

+237
-0
lines changed

src/lib/es6.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3580,6 +3580,7 @@ interface PromiseLike<T> {
35803580
* @returns A Promise for the completion of which ever callback is executed.
35813581
*/
35823582
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
3583+
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>;
35833584
}
35843585

35853586
/**
@@ -3593,6 +3594,7 @@ interface Promise<T> {
35933594
* @returns A Promise for the completion of which ever callback is executed.
35943595
*/
35953596
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>;
3597+
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): Promise<TResult>;
35963598

35973599
/**
35983600
* Attaches a callback for only the rejection of the Promise.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//// [promiseVoidErrorCallback.ts]
2+
interface T1 {
3+
__t1: string;
4+
}
5+
6+
interface T2 {
7+
__t2: string;
8+
}
9+
10+
interface T3 {
11+
__t3: string;
12+
}
13+
14+
function f1(): Promise<T1> {
15+
return Promise.resolve({ __t1: "foo_t1" });
16+
}
17+
18+
function f2(x: T1): T2 {
19+
return { __t2: x.__t1 + ":foo_21" };
20+
}
21+
22+
var x3 = f1()
23+
.then(f2, (e: Error) => {
24+
throw e;
25+
})
26+
.then((x: T2) => {
27+
return { __t3: x.__t2 + "bar" };
28+
});
29+
30+
//// [promiseVoidErrorCallback.js]
31+
function f1() {
32+
return Promise.resolve({ __t1: "foo_t1" });
33+
}
34+
function f2(x) {
35+
return { __t2: x.__t1 + ":foo_21" };
36+
}
37+
var x3 = f1()
38+
.then(f2, (e) => {
39+
throw e;
40+
})
41+
.then((x) => {
42+
return { __t3: x.__t2 + "bar" };
43+
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
=== tests/cases/compiler/promiseVoidErrorCallback.ts ===
2+
interface T1 {
3+
>T1 : Symbol(T1, Decl(promiseVoidErrorCallback.ts, 0, 0))
4+
5+
__t1: string;
6+
>__t1 : Symbol(__t1, Decl(promiseVoidErrorCallback.ts, 0, 14))
7+
}
8+
9+
interface T2 {
10+
>T2 : Symbol(T2, Decl(promiseVoidErrorCallback.ts, 2, 1))
11+
12+
__t2: string;
13+
>__t2 : Symbol(__t2, Decl(promiseVoidErrorCallback.ts, 4, 14))
14+
}
15+
16+
interface T3 {
17+
>T3 : Symbol(T3, Decl(promiseVoidErrorCallback.ts, 6, 1))
18+
19+
__t3: string;
20+
>__t3 : Symbol(__t3, Decl(promiseVoidErrorCallback.ts, 8, 14))
21+
}
22+
23+
function f1(): Promise<T1> {
24+
>f1 : Symbol(f1, Decl(promiseVoidErrorCallback.ts, 10, 1))
25+
>Promise : Symbol(Promise, Decl(lib.d.ts, 4769, 1), Decl(lib.d.ts, 4854, 11))
26+
>T1 : Symbol(T1, Decl(promiseVoidErrorCallback.ts, 0, 0))
27+
28+
return Promise.resolve({ __t1: "foo_t1" });
29+
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.d.ts, 4836, 39), Decl(lib.d.ts, 4843, 54))
30+
>Promise : Symbol(Promise, Decl(lib.d.ts, 4769, 1), Decl(lib.d.ts, 4854, 11))
31+
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.d.ts, 4836, 39), Decl(lib.d.ts, 4843, 54))
32+
>__t1 : Symbol(__t1, Decl(promiseVoidErrorCallback.ts, 13, 28))
33+
}
34+
35+
function f2(x: T1): T2 {
36+
>f2 : Symbol(f2, Decl(promiseVoidErrorCallback.ts, 14, 1))
37+
>x : Symbol(x, Decl(promiseVoidErrorCallback.ts, 16, 12))
38+
>T1 : Symbol(T1, Decl(promiseVoidErrorCallback.ts, 0, 0))
39+
>T2 : Symbol(T2, Decl(promiseVoidErrorCallback.ts, 2, 1))
40+
41+
return { __t2: x.__t1 + ":foo_21" };
42+
>__t2 : Symbol(__t2, Decl(promiseVoidErrorCallback.ts, 17, 12))
43+
>x.__t1 : Symbol(T1.__t1, Decl(promiseVoidErrorCallback.ts, 0, 14))
44+
>x : Symbol(x, Decl(promiseVoidErrorCallback.ts, 16, 12))
45+
>__t1 : Symbol(T1.__t1, Decl(promiseVoidErrorCallback.ts, 0, 14))
46+
}
47+
48+
var x3 = f1()
49+
>x3 : Symbol(x3, Decl(promiseVoidErrorCallback.ts, 20, 3))
50+
>f1() .then(f2, (e: Error) => { throw e;}) .then : Symbol(Promise.then, Decl(lib.d.ts, 4774, 22), Decl(lib.d.ts, 4781, 158))
51+
>f1() .then : Symbol(Promise.then, Decl(lib.d.ts, 4774, 22), Decl(lib.d.ts, 4781, 158))
52+
>f1 : Symbol(f1, Decl(promiseVoidErrorCallback.ts, 10, 1))
53+
54+
.then(f2, (e: Error) => {
55+
>then : Symbol(Promise.then, Decl(lib.d.ts, 4774, 22), Decl(lib.d.ts, 4781, 158))
56+
>f2 : Symbol(f2, Decl(promiseVoidErrorCallback.ts, 14, 1))
57+
>e : Symbol(e, Decl(promiseVoidErrorCallback.ts, 21, 15))
58+
>Error : Symbol(Error, Decl(lib.d.ts, 876, 38), Decl(lib.d.ts, 889, 11))
59+
60+
throw e;
61+
>e : Symbol(e, Decl(promiseVoidErrorCallback.ts, 21, 15))
62+
63+
})
64+
.then((x: T2) => {
65+
>then : Symbol(Promise.then, Decl(lib.d.ts, 4774, 22), Decl(lib.d.ts, 4781, 158))
66+
>x : Symbol(x, Decl(promiseVoidErrorCallback.ts, 24, 11))
67+
>T2 : Symbol(T2, Decl(promiseVoidErrorCallback.ts, 2, 1))
68+
69+
return { __t3: x.__t2 + "bar" };
70+
>__t3 : Symbol(__t3, Decl(promiseVoidErrorCallback.ts, 25, 12))
71+
>x.__t2 : Symbol(T2.__t2, Decl(promiseVoidErrorCallback.ts, 4, 14))
72+
>x : Symbol(x, Decl(promiseVoidErrorCallback.ts, 24, 11))
73+
>__t2 : Symbol(T2.__t2, Decl(promiseVoidErrorCallback.ts, 4, 14))
74+
75+
});
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
=== tests/cases/compiler/promiseVoidErrorCallback.ts ===
2+
interface T1 {
3+
>T1 : T1
4+
5+
__t1: string;
6+
>__t1 : string
7+
}
8+
9+
interface T2 {
10+
>T2 : T2
11+
12+
__t2: string;
13+
>__t2 : string
14+
}
15+
16+
interface T3 {
17+
>T3 : T3
18+
19+
__t3: string;
20+
>__t3 : string
21+
}
22+
23+
function f1(): Promise<T1> {
24+
>f1 : () => Promise<T1>
25+
>Promise : Promise<T>
26+
>T1 : T1
27+
28+
return Promise.resolve({ __t1: "foo_t1" });
29+
>Promise.resolve({ __t1: "foo_t1" }) : Promise<{ __t1: string; }>
30+
>Promise.resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
31+
>Promise : PromiseConstructor
32+
>resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
33+
>{ __t1: "foo_t1" } : { __t1: string; }
34+
>__t1 : string
35+
>"foo_t1" : string
36+
}
37+
38+
function f2(x: T1): T2 {
39+
>f2 : (x: T1) => T2
40+
>x : T1
41+
>T1 : T1
42+
>T2 : T2
43+
44+
return { __t2: x.__t1 + ":foo_21" };
45+
>{ __t2: x.__t1 + ":foo_21" } : { __t2: string; }
46+
>__t2 : string
47+
>x.__t1 + ":foo_21" : string
48+
>x.__t1 : string
49+
>x : T1
50+
>__t1 : string
51+
>":foo_21" : string
52+
}
53+
54+
var x3 = f1()
55+
>x3 : Promise<{ __t3: string; }>
56+
>f1() .then(f2, (e: Error) => { throw e;}) .then((x: T2) => { return { __t3: x.__t2 + "bar" };}) : Promise<{ __t3: string; }>
57+
>f1() .then(f2, (e: Error) => { throw e;}) .then : { <TResult>(onfulfilled?: (value: T2) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>; <TResult>(onfulfilled?: (value: T2) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): Promise<TResult>; }
58+
>f1() .then(f2, (e: Error) => { throw e;}) : Promise<T2>
59+
>f1() .then : { <TResult>(onfulfilled?: (value: T1) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>; <TResult>(onfulfilled?: (value: T1) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): Promise<TResult>; }
60+
>f1() : Promise<T1>
61+
>f1 : () => Promise<T1>
62+
63+
.then(f2, (e: Error) => {
64+
>then : { <TResult>(onfulfilled?: (value: T1) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>; <TResult>(onfulfilled?: (value: T1) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): Promise<TResult>; }
65+
>f2 : (x: T1) => T2
66+
>(e: Error) => { throw e;} : (e: Error) => void
67+
>e : Error
68+
>Error : Error
69+
70+
throw e;
71+
>e : Error
72+
73+
})
74+
.then((x: T2) => {
75+
>then : { <TResult>(onfulfilled?: (value: T2) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>; <TResult>(onfulfilled?: (value: T2) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): Promise<TResult>; }
76+
>(x: T2) => { return { __t3: x.__t2 + "bar" };} : (x: T2) => { __t3: string; }
77+
>x : T2
78+
>T2 : T2
79+
80+
return { __t3: x.__t2 + "bar" };
81+
>{ __t3: x.__t2 + "bar" } : { __t3: string; }
82+
>__t3 : string
83+
>x.__t2 + "bar" : string
84+
>x.__t2 : string
85+
>x : T2
86+
>__t2 : string
87+
>"bar" : string
88+
89+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@target: ES6
2+
interface T1 {
3+
__t1: string;
4+
}
5+
6+
interface T2 {
7+
__t2: string;
8+
}
9+
10+
interface T3 {
11+
__t3: string;
12+
}
13+
14+
function f1(): Promise<T1> {
15+
return Promise.resolve({ __t1: "foo_t1" });
16+
}
17+
18+
function f2(x: T1): T2 {
19+
return { __t2: x.__t1 + ":foo_21" };
20+
}
21+
22+
var x3 = f1()
23+
.then(f2, (e: Error) => {
24+
throw e;
25+
})
26+
.then((x: T2) => {
27+
return { __t3: x.__t2 + "bar" };
28+
});

0 commit comments

Comments
 (0)