Fix typing for Promises so that a void error callback doesn't mess up inference

This commit is contained in:
Jason Freeman 2015-05-06 15:53:01 -07:00
parent 14362b0ca5
commit 498f315256
5 changed files with 237 additions and 0 deletions

2
src/lib/es6.d.ts vendored
View File

@ -3580,6 +3580,7 @@ interface PromiseLike<T> {
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>;
}
/**
@ -3593,6 +3594,7 @@ interface Promise<T> {
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>;
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): Promise<TResult>;
/**
* Attaches a callback for only the rejection of the Promise.

View File

@ -0,0 +1,43 @@
//// [promiseVoidErrorCallback.ts]
interface T1 {
__t1: string;
}
interface T2 {
__t2: string;
}
interface T3 {
__t3: string;
}
function f1(): Promise<T1> {
return Promise.resolve({ __t1: "foo_t1" });
}
function f2(x: T1): T2 {
return { __t2: x.__t1 + ":foo_21" };
}
var x3 = f1()
.then(f2, (e: Error) => {
throw e;
})
.then((x: T2) => {
return { __t3: x.__t2 + "bar" };
});
//// [promiseVoidErrorCallback.js]
function f1() {
return Promise.resolve({ __t1: "foo_t1" });
}
function f2(x) {
return { __t2: x.__t1 + ":foo_21" };
}
var x3 = f1()
.then(f2, (e) => {
throw e;
})
.then((x) => {
return { __t3: x.__t2 + "bar" };
});

View File

@ -0,0 +1,75 @@
=== tests/cases/compiler/promiseVoidErrorCallback.ts ===
interface T1 {
>T1 : Symbol(T1, Decl(promiseVoidErrorCallback.ts, 0, 0))
__t1: string;
>__t1 : Symbol(__t1, Decl(promiseVoidErrorCallback.ts, 0, 14))
}
interface T2 {
>T2 : Symbol(T2, Decl(promiseVoidErrorCallback.ts, 2, 1))
__t2: string;
>__t2 : Symbol(__t2, Decl(promiseVoidErrorCallback.ts, 4, 14))
}
interface T3 {
>T3 : Symbol(T3, Decl(promiseVoidErrorCallback.ts, 6, 1))
__t3: string;
>__t3 : Symbol(__t3, Decl(promiseVoidErrorCallback.ts, 8, 14))
}
function f1(): Promise<T1> {
>f1 : Symbol(f1, Decl(promiseVoidErrorCallback.ts, 10, 1))
>Promise : Symbol(Promise, Decl(lib.d.ts, 4769, 1), Decl(lib.d.ts, 4854, 11))
>T1 : Symbol(T1, Decl(promiseVoidErrorCallback.ts, 0, 0))
return Promise.resolve({ __t1: "foo_t1" });
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.d.ts, 4836, 39), Decl(lib.d.ts, 4843, 54))
>Promise : Symbol(Promise, Decl(lib.d.ts, 4769, 1), Decl(lib.d.ts, 4854, 11))
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.d.ts, 4836, 39), Decl(lib.d.ts, 4843, 54))
>__t1 : Symbol(__t1, Decl(promiseVoidErrorCallback.ts, 13, 28))
}
function f2(x: T1): T2 {
>f2 : Symbol(f2, Decl(promiseVoidErrorCallback.ts, 14, 1))
>x : Symbol(x, Decl(promiseVoidErrorCallback.ts, 16, 12))
>T1 : Symbol(T1, Decl(promiseVoidErrorCallback.ts, 0, 0))
>T2 : Symbol(T2, Decl(promiseVoidErrorCallback.ts, 2, 1))
return { __t2: x.__t1 + ":foo_21" };
>__t2 : Symbol(__t2, Decl(promiseVoidErrorCallback.ts, 17, 12))
>x.__t1 : Symbol(T1.__t1, Decl(promiseVoidErrorCallback.ts, 0, 14))
>x : Symbol(x, Decl(promiseVoidErrorCallback.ts, 16, 12))
>__t1 : Symbol(T1.__t1, Decl(promiseVoidErrorCallback.ts, 0, 14))
}
var x3 = f1()
>x3 : Symbol(x3, Decl(promiseVoidErrorCallback.ts, 20, 3))
>f1() .then(f2, (e: Error) => { throw e;}) .then : Symbol(Promise.then, Decl(lib.d.ts, 4774, 22), Decl(lib.d.ts, 4781, 158))
>f1() .then : Symbol(Promise.then, Decl(lib.d.ts, 4774, 22), Decl(lib.d.ts, 4781, 158))
>f1 : Symbol(f1, Decl(promiseVoidErrorCallback.ts, 10, 1))
.then(f2, (e: Error) => {
>then : Symbol(Promise.then, Decl(lib.d.ts, 4774, 22), Decl(lib.d.ts, 4781, 158))
>f2 : Symbol(f2, Decl(promiseVoidErrorCallback.ts, 14, 1))
>e : Symbol(e, Decl(promiseVoidErrorCallback.ts, 21, 15))
>Error : Symbol(Error, Decl(lib.d.ts, 876, 38), Decl(lib.d.ts, 889, 11))
throw e;
>e : Symbol(e, Decl(promiseVoidErrorCallback.ts, 21, 15))
})
.then((x: T2) => {
>then : Symbol(Promise.then, Decl(lib.d.ts, 4774, 22), Decl(lib.d.ts, 4781, 158))
>x : Symbol(x, Decl(promiseVoidErrorCallback.ts, 24, 11))
>T2 : Symbol(T2, Decl(promiseVoidErrorCallback.ts, 2, 1))
return { __t3: x.__t2 + "bar" };
>__t3 : Symbol(__t3, Decl(promiseVoidErrorCallback.ts, 25, 12))
>x.__t2 : Symbol(T2.__t2, Decl(promiseVoidErrorCallback.ts, 4, 14))
>x : Symbol(x, Decl(promiseVoidErrorCallback.ts, 24, 11))
>__t2 : Symbol(T2.__t2, Decl(promiseVoidErrorCallback.ts, 4, 14))
});

View File

@ -0,0 +1,89 @@
=== tests/cases/compiler/promiseVoidErrorCallback.ts ===
interface T1 {
>T1 : T1
__t1: string;
>__t1 : string
}
interface T2 {
>T2 : T2
__t2: string;
>__t2 : string
}
interface T3 {
>T3 : T3
__t3: string;
>__t3 : string
}
function f1(): Promise<T1> {
>f1 : () => Promise<T1>
>Promise : Promise<T>
>T1 : T1
return Promise.resolve({ __t1: "foo_t1" });
>Promise.resolve({ __t1: "foo_t1" }) : Promise<{ __t1: string; }>
>Promise.resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
>Promise : PromiseConstructor
>resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
>{ __t1: "foo_t1" } : { __t1: string; }
>__t1 : string
>"foo_t1" : string
}
function f2(x: T1): T2 {
>f2 : (x: T1) => T2
>x : T1
>T1 : T1
>T2 : T2
return { __t2: x.__t1 + ":foo_21" };
>{ __t2: x.__t1 + ":foo_21" } : { __t2: string; }
>__t2 : string
>x.__t1 + ":foo_21" : string
>x.__t1 : string
>x : T1
>__t1 : string
>":foo_21" : string
}
var x3 = f1()
>x3 : Promise<{ __t3: string; }>
>f1() .then(f2, (e: Error) => { throw e;}) .then((x: T2) => { return { __t3: x.__t2 + "bar" };}) : Promise<{ __t3: string; }>
>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>; }
>f1() .then(f2, (e: Error) => { throw e;}) : Promise<T2>
>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>; }
>f1() : Promise<T1>
>f1 : () => Promise<T1>
.then(f2, (e: Error) => {
>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>; }
>f2 : (x: T1) => T2
>(e: Error) => { throw e;} : (e: Error) => void
>e : Error
>Error : Error
throw e;
>e : Error
})
.then((x: T2) => {
>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>; }
>(x: T2) => { return { __t3: x.__t2 + "bar" };} : (x: T2) => { __t3: string; }
>x : T2
>T2 : T2
return { __t3: x.__t2 + "bar" };
>{ __t3: x.__t2 + "bar" } : { __t3: string; }
>__t3 : string
>x.__t2 + "bar" : string
>x.__t2 : string
>x : T2
>__t2 : string
>"bar" : string
});

View File

@ -0,0 +1,28 @@
//@target: ES6
interface T1 {
__t1: string;
}
interface T2 {
__t2: string;
}
interface T3 {
__t3: string;
}
function f1(): Promise<T1> {
return Promise.resolve({ __t1: "foo_t1" });
}
function f2(x: T1): T2 {
return { __t2: x.__t1 + ":foo_21" };
}
var x3 = f1()
.then(f2, (e: Error) => {
throw e;
})
.then((x: T2) => {
return { __t3: x.__t2 + "bar" };
});