- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.1k
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>;
 }