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

Type inference not working with extends generic argument and keyof and --strictNullChecks #13922

Closed
Knagis opened this issue Feb 7, 2017 · 5 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@Knagis
Copy link
Contributor

Knagis commented Feb 7, 2017

The title of the bug should probably be improved - I was not able to come up with something that encapsulates the issue.

TypeScript Version: 2.1.5, compiling using --strictNullChecks

This issue seems not to be present in the TypeScript playground (2.1.4-insiders.20161201):

Code

interface Foo {
    foo: number|null;
}

export class Base<T extends Foo> {
    public style: Readonly<T>;

    public styleDirect: Readonly<Foo>;

    public reqNumber(a: number) {
    }

    public reqNumberNull(a: number|null) {
    }

    public method() {
	// works
        this.reqNumberNull(this.style.foo);


	// works
        this.reqNumber(this.styleDirect.foo || 0);


        // does not work
        this.reqNumber(this.style.foo || 0);
    }
}

Expected behavior:

All three method calls should compile correctly.

Actual behavior:

test.ts(26,24): error TS2345: Argument of type 'T["foo"] | 0' is not assignable to parameter of type 'number'.
  Type 'T["foo"]' is not assignable to type 'number'.
    Type 'number | null' is not assignable to type 'number'.
      Type 'null' is not assignable to type 'number'.
@Knagis
Copy link
Contributor Author

Knagis commented Feb 24, 2017

This issue is still present in version 2.2.1-insiders.20170217

@patsissons
Copy link

Running into something similar (i think), on 2.2.2. Below is some sample code that capture the issue I was seeing with generic type inference when dealing with a generic union type.

// some complex generic union type alias
type ArrayOrValue<T> = Array<T> | T;

// sample function to consume the complex type above
function foo1<T>(x: ArrayOrValue<T>) {
  return x;
}

// some nullable input
let bar: string | undefined;

// bar being inferred as string instead of string | undefined
foo1(bar);
// but there is no problem if the generic typing is explicit
foo1<string | undefined>(bar);

// simpler version of foo1
function foo2<T>(x: T) {
  return x;
}

// these calls have no problem with type inference
foo2(bar);
foo2<string | undefined>(bar);

@mhegazy
Copy link
Contributor

mhegazy commented May 16, 2017

@ahejlsberg looks like this is one case that was not handled by #15576. any thoughts on this?

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label May 24, 2017
@RyanCavanaugh RyanCavanaugh added Design Limitation Constraints of the existing architecture prevent this from being fixed and removed Needs Investigation This issue needs a team member to investigate its status. labels Sep 18, 2019
@RyanCavanaugh
Copy link
Member

The problem here is Readonly<T> - TS can't perform the higher-order reasoning to know what comes out the other side is a narrowable thing.

@Knagis
Copy link
Contributor Author

Knagis commented Jan 17, 2023

Turns out this issue has been fixed since 4.3.

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

No branches or pull requests

4 participants