Description
TypeScript Version: 2.1.1 / nightly (2.2.0-dev.201xxxxx)
Code
interface A { m(): Promise<any> }
interface B { m(): Promise<number> }
function a(o: A): Promise<number> {
return Promise.resolve()
.then(_ => o.m());
}
function adash(o: A): Promise<number> {
return o.m();
}
function b(o: B): Promise<number> {
return Promise.resolve()
.then(_ => o.m());
}
Expected behavior:
Should compile.
Actual behavior:
function a
doesn't compile. The return type of the return statement is inferred as Promise<void>
, while it should be inferred as Promise<any>
, which is compatible with the intended return type (Promise<number>
) of the parent function (a
), just like type is correctly inferred as Promise<number>
in the function b
.
The offending part here is the library definitions for the Promise
interface, at https://github.com/Microsoft/TypeScript/blob/master/lib/lib.es2015.promise.d.ts#L31. The linked definition of then
is matched on the result of Promise.resolve()
, which is a Promise<void>
, and the return type is inferred as Promise<void>
only. Apparently order matters, and the correct matching for that expression should be https://github.com/Microsoft/TypeScript/blob/master/lib/lib.es2015.promise.d.ts#L47 instead, so the return type is inferred as Promise<any>
instead.
Simply re-ordering those definitions of .then
solves the issue. But I am not sure what the further implications are.
diff --git a/src/lib/es2015.promise.d.ts b/src/lib/es2015.promise.d.ts
index e27da2c..63fef0f 100644
--- a/src/lib/es2015.promise.d.ts
+++ b/src/lib/es2015.promise.d.ts
@@ -8,7 +8,7 @@ interface Promise<T> {
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
- then(onfulfilled?: ((value: T) => T | PromiseLike<T>) | undefined | null, onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): Promise<T>;
+ then<TResult>(onfulfilled: ((value: T) => T | PromiseLike<T>) | undefined | null, onrejected: (reason: any) => TResult | PromiseLike<TResult>): Promise<T | TResult>;
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
@@ -16,7 +16,7 @@ interface Promise<T> {
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
- then<TResult>(onfulfilled: ((value: T) => T | PromiseLike<T>) | undefined | null, onrejected: (reason: any) => TResult | PromiseLike<TResult>): Promise<T | TResult>;
+ then<TResult>(onfulfilled: (value: T) => TResult | PromiseLike<TResult>, onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<TResult>;
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
@@ -24,7 +24,7 @@ interface Promise<T> {
* @param onrejected The callback to execute when the Promise is rejected.
* @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>) | undefined | null): Promise<TResult>;
+ then<TResult1, TResult2>(onfulfilled: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): Promise<TResult1 | TResult2>;
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
@@ -32,7 +32,7 @@ interface Promise<T> {
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
- then<TResult1, TResult2>(onfulfilled: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): Promise<TResult1 | TResult2>;
+ then(onfulfilled?: ((value: T) => T | PromiseLike<T>) | undefined | null, onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): Promise<T>;
/**
* Attaches a callback for only the rejection of the Promise.
@@ -251,4 +251,4 @@ interface PromiseConstructor {
resolve(): Promise<void>;
}