TypeScript Version: 2.1.4
Code
// A *self-contained* demonstration of the problem follows...
export interface MyInterface {
myFunction(): Promise<number | string>;
}
export class MyClass implements MyInterface {
async myFunction() { // inferred return type Promise<number | string | string[]>
let num = 1;
let text = 'text';
if (num) {
return num;
}
if (text) {
return text;
}
return [text];
}
}
Expected behavior:
TS throws an error that MyClass incorrectly implements MyInterface
type Promise<number | string | string[]> not assignable to Promise<number | string>
otherwise a client using the class as MyInterface can call the method and only handle a return promise of string or number and have errors when the promise is resolved with the array.
Actual behavior:
No error is thrown. (It's worth noting this doesn't repro without the generic. If for example the method were not async.) This also is not thrown if the return type is manually specified as Promise<number | string | string[]> just to be clear inference is not to blame.
here's an even simpler example that doesn't require classes or interfaces
const myPromise: Promise<string> =
new Promise<string | string[]>((resolve) => { resolve(['anything']) })
myPromise.then(value => {
value.substr(0, 3); //throws an error because arrays lack this function
});
and using inference rather than explicit same thing:
const myPromise: Promise<string> = new Promise((resolve) => {
let text = '';
if (text) {
resolve(text);
}
resolve([text]);
});
myPromise.then(value => {
value.substr(0, 3); //throws an error because arrays lack this function
});
code example without the generic to prove that normally a superset is unassignable
function myFunction() { // inferred return 'number | string | string[]'
let num = 1;
let text = 'text';
if (num) {
return num;
}
if (text) {
return text;
}
return [text];
}
const myValue: string | number = myFunction(); //ts throws unassignable error
@gmoothart @evmar @bb @joshk @huerlisi sorry to ping you all. not sure who should take a look at this. seems like a pretty major bug.
This is actually a result of structural compatibility and function parameter bivariance. Essentially when Promise#then is compared between the two, the parameter type of arguments are compared in a bivariant way. Since the contravariant side succeeds, the two are compatible in either direction.
This is undesirable, but we're thinking about fixes. See this section in our FAQ for more details.
@DanielRosenwasser ok :) i don't fully understand the terms you used but i think i get the gist. glad to hear it's being worked on :)
The correct error should be reported with https://github.com/Microsoft/TypeScript/pull/15104.
awesome!
On Thu, 18 May 2017 at 09:53 Mohamed Hegazy notifications@github.com
wrote:
The correct error should be reported with #15104
https://github.com/Microsoft/TypeScript/pull/15104.β
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/13970#issuecomment-302469238,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABE5mDzTMaRcBXRA2EtEyOC78AXJCYAXks5r7HdsgaJpZM4L72sH
.
@DanielRosenwasser ok :) i don't fully understand the terms you used but i think i get the gist. glad to hear it's being worked on :)
Sorry about that - that was a bit more jargon-y than I realized. π

hahahaha! best. thanks again for the fix :)
On Thu, 18 May 2017 at 12:50 Daniel Rosenwasser notifications@github.com
wrote:
@DanielRosenwasser https://github.com/danielrosenwasser ok :) i don't
fully understand the terms you used but i think i get the gist. glad to
hear it's being worked on :)Sorry about that - that was a bit more jargon-y than I realized. π
[image: image]
https://cloud.githubusercontent.com/assets/972891/26220693/7999d318-3bc8-11e7-9f79-44ad256789a9.pngβ
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/13970#issuecomment-302522148,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABE5mPC3p7xJ_KZahOLNexga_aW57F64ks5r7KD_gaJpZM4L72sH
.
Most helpful comment
Sorry about that - that was a bit more jargon-y than I realized. π