Repository navigation
Promises of different types should not be compatible #9953
Description
Activity
In the definition of
Promise<T>in lib.d.ts, if you comment out the nullary overload ofthen, then you get the expected behaviour. I do not understand why, I was just trying to reproduce the behaviour with a simpler case and discovered that.// in lib.d.ts: interface Promise<T> { /*...*/ then<TResult1, TResult2>(onfulfilled: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): Promise<TResult1 | TResult2>; /*...*/ // then(): Promise<T>; <===== comment this one out /*...*/ } // in code.ts: const x: Promise<string> = Promise.resolve(""); const y: Promise<number> = x; // ERROR: 'Promise<string> is not assignable to 'Promise<number>'
Reacted by Sean MiddleditchI came up with those overloads in #9193, but under closer examination they are actually subtly wrong. TypeScript's model of function arguments assumes that extra args beyond those declared in the signature are ignored - and therefore, a function signature is assignable to a function signature with more parameters. Although you can pass 0 or 1 arguments to
Promise.then, it does not ignore its first and second arguments; we do not want this rule applying to it.I think the right way to declare
Promise.thenis to make all the overloads 2-arg, with optional parameters of type null (technically, any non-function can be used to get the passthrough behavior, but passing anything other than null/undefined is almost certainly a mistake)interface Promise<T> { then(onfulfilled?: null, onrejected?: null): Promise<T>; then<TResult>(onfulfilled: (value: T) => TResult | PromiseLike<TResult>, onrejected?: null): Promise<TResult>; // other overloads here }EDIT: This only fixes the problem when
--strictNullChecksis on. Changingnulltoneverdoesn't help, but changing it tostringdoes. Not sure why...Reacted by Sean MiddleditchOliverJAsh commented
on Sep 23, 2016 ContributorMore actionsIs this still an issue?
const commits: Promise<number> = Promise.resolve('foo') // no error!
thanks Oliver Joseph Ash (@OliverJAsh). this should be fixed after Ron Buckton (@rbuckton)'s latest change to the Promise definitions.
- addedFixedA PR has been merged for this issueA PR has been merged for this issue
on Sep 29, 2016 - removedFixedA PR has been merged for this issueA PR has been merged for this issue
on Oct 31, 2016 - addedFixedA PR has been merged for this issueA PR has been merged for this issue
on Apr 19, 2017 - locked and limited conversation to collaborators
on Jun 19, 2018
TypeScript Version: nightly
Code
Expected behavior:
Compiler error on line 2.
Actual behavior:
No error.