You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The problem here is how function return type is inferred.
An even reduced example.
declarevarrejected: Promise<never>declarevarresolved: Promise<void>functionThen(n: number){// inferred as Promise<never>, so it is a subtype of `Promise<number>`returnn!==200 ? rejected : resolved}vara: Promise<void>=Promise.resolve(4).then(Then);// error here because then resolves to Promise<number>
Current workaround is annotate your function return type to Promise<void>.
The problem may be function signature with void and never as argument and return type. Curiously, if we can add a type tag, just like nominal-type brand, it can resolve the problem. Since type parameter T is covariant in Promise and TypeScript's property is covariant by default, the type tag does help inference.
interfacePromise<T>{'@@__typeTag': T/// other signatures ...}
The code above compiles, Promise<void> and Promise<never> are mutually assignable. So in the conditional ternary, the first operand type is preferred as the result of subtype reduction. If you flip the position of x and y, like var a = Math.random() ? y : x;, a is inferred as Promise<never>. This is a reasonable behavior.
Promise at type level is effectively a collection of function type. So I reduced the problem down to this.
It compiles because of bivariance, which is the known old problem all the way back to #1394, #10717.
I wonder whether the type tag approach mentioned above can mitigate this by guaranteeing covariant behavior. Yet I'm happier to see strict variance can come to TypeScript.
The compiler complains on the console.log call because 'instanceOfB' is identified as being TypeA which does not have member 'b'. Additionally, VSCode also sees the issue (which makes sense).
instanceB should get its type signature from the return signature of the value return in the previous then, but it is not.
I even tried EXPLICITLY defining the return type of the function passed to .then, but it still complained:
.then((instanceOfA): Promise<TypeB>=>fnB())
This has made it impossible for us to update to 2.1 without doing nasty stuff like double casting:
Lucas Lacroix (@raijinsetsu) I have the same problem. I have chains of promises that transforms the information down the line. This compiles fine with tsc 2.0.8, but breaks in 2.1 - in that the compiler insists the type is the same as on the root promise.
I suspect it might be the library definitions, the d.ts file, that is outdated - but not sure how to progress.
Sublime Text with Typescript also complains about this issue, even if I only have tsc 2.0.8 on my machine. This mix of versions makes the code challenging to work with.
Any help on this would be greatly appreciated.
Edit: Seems that this is under investigation in: 10977
Activity
HerringtonDarkholme commentedon Dec 14, 2016
The problem here is how function return type is inferred.
An even reduced example.
Current workaround is annotate your function return type to
Promise<void>.The problem may be function signature with void and never as argument and return type. Curiously, if we can add a type tag, just like nominal-type brand, it can resolve the problem. Since type parameter
Tis covariant in Promise and TypeScript's property is covariant by default, the type tag does help inference.Ron Buckton (@rbuckton) what's your opinion?
DanielRosenwasser commentedon Dec 14, 2016
This is odd - if I write the following:
the type of
aisPromise<void>, and I believe the function should be doing the same.HerringtonDarkholme commentedon Dec 15, 2016
Daniel Rosenwasser (@DanielRosenwasser)
It seems the problem is assignability for
neverandvoidin return/parameter. For exampleThe code above compiles,
Promise<void>andPromise<never>are mutually assignable. So in the conditional ternary, the first operand type is preferred as the result of subtype reduction. If you flip the position of x and y, likevar a = Math.random() ? y : x;, a is inferred asPromise<never>. This is a reasonable behavior.Promise at type level is effectively a collection of function type. So I reduced the problem down to this.
It compiles because of bivariance, which is the known old problem all the way back to #1394, #10717.
I wonder whether the type tag approach mentioned above can mitigate this by guaranteeing covariant behavior. Yet I'm happier to see strict variance can come to TypeScript.
raijinsetsu commentedon Jan 5, 2017
I'm having a similar issue which I am not able to work-around with any of the above information.
The compiler complains on the console.log call because 'instanceOfB' is identified as being TypeA which does not have member 'b'. Additionally, VSCode also sees the issue (which makes sense).
instanceB should get its type signature from the return signature of the value return in the previous then, but it is not.
I even tried EXPLICITLY defining the return type of the function passed to .then, but it still complained:
This has made it impossible for us to update to 2.1 without doing nasty stuff like double casting:
tvedtorama commentedon Jan 12, 2017
Lucas Lacroix (@raijinsetsu) I have the same problem. I have chains of promises that transforms the information down the line. This compiles fine with tsc 2.0.8, but breaks in 2.1 - in that the compiler insists the type is the same as on the root promise.
I suspect it might be the library definitions, the d.ts file, that is outdated - but not sure how to progress.
Sublime Text with Typescript also complains about this issue, even if I only have tsc 2.0.8 on my machine. This mix of versions makes the code challenging to work with.
Any help on this would be greatly appreciated.
Edit: Seems that this is under investigation in: 10977