Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Casting generics ignores --strictNullCheck #13513

Closed
0xShammah opened this issue Jan 16, 2017 · 4 comments
Closed

Casting generics ignores --strictNullCheck #13513

0xShammah opened this issue Jan 16, 2017 · 4 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@0xShammah
Copy link

0xShammah commented Jan 16, 2017

TypeScript Version: 2.1.5

Code
Minimal example that compiles just fine:

let x: Promise<string | undefined> = Promise.resolve(undefined);
let y: Promise<string> = x;

Small usage example in which I encountered the bug:

interface ITest {
    test(): Promise<string>;
}

class Test implements ITest{
    test(): Promise<string | undefined> {
        return Promise.resolve(undefined);
    }
}

var test = new Test();
test.test().then(console.log);

Expected behavior:
A compile error: the type Promise<string | undefined> does not match the type Promise<string>. I should not be able to cast undefined to string.

Actual behavior:
No errors.

@0xShammah
Copy link
Author

This might be related to #10717 and https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-function-parameters-bivariant

@RyanCavanaugh
Copy link
Member

@rbuckton does this get fixed by your recent change?

@rbuckton
Copy link
Member

@RyanCavanaugh: if you mean #13487 then no, I do not believe it addresses this issue. In this case we are running afoul of parameter bivariance and how we handle structural typing. Though the checker sees that the type arguments are not assignable, we continue on to a structural check. During the structural check, we end up comparing the assignability of the onfulfilled callback for then, and we see that (value: string | undefined) => any is assignable to (value: string) => any. Unfortunately, we cannot fix this without branding Promise in some fashion or introducing some form of covariance or contravariance.

@mhegazy mhegazy added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jan 26, 2017
@whymarrh
Copy link

Is this an example of the same or a similar issue (in v2.1.5)? Would #10717/#13257 fix this?

class A {
    constructor(readonly message: string) {}
}

class B extends A {
    lastCharacter() {
        return this.message.substring(this.message.length - 1);
    }
}

const pick: (s: string) => Promise<B> = (s: string) =>
    Promise.resolve(new A(s));

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

5 participants