Skip to content

Generic inference fails when adding bogus optional generics #23601

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

Closed
SimonMeskens opened this issue Apr 21, 2018 · 3 comments
Closed

Generic inference fails when adding bogus optional generics #23601

SimonMeskens opened this issue Apr 21, 2018 · 3 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@SimonMeskens
Copy link

TypeScript Version: 2.9.0-dev.20180420

Code

    let id = <T>(b: Test<T>) => 0;
    type Test<T> = (b: T) => any;

    let t = (b: { a: number }) => 0;
    let u = <U>(b: { a: number }) => 0;

    id(t);
    id(u); // Fails on `u`
    let v: Test<{a: number}> = u; // But this passes

    let id2 = <T>(b: Test2<T>) => 0;
    type Test2<T> = <U>(b: T) => any;

    id2(t);
    id2(u); // Now it passes

Expected behavior: I don't even know what the intent here is

Actual behavior: As noted in code comments

Here's the error I get on u:

Argument of type '<U>(b: { a: number; }) => number' is not assignable to parameter of type 'Test<{}>'.
  Types of parameters 'b' and 'b' are incompatible.
    Type '{}' is not assignable to type '{ a: number; }'.
      Property 'a' is missing in type '{}'.

I ran into this problem while writing some complex code, after reducing and reducing forever, I managed to track it down to this very abstract example. My apologies if it's a bit hard to follow. I feel like this is a bug? At the very least it's very unexpected behavior and the error messages surrounding this issue tend to be very cryptic.

@mhegazy mhegazy added the Bug A bug in TypeScript label Apr 21, 2018
@ahejlsberg
Copy link
Member

Here's a repro that is a bit easier to read:

declare function id<T>(x: (b: T) => any): number;
declare function test<U>(b: string): number;

id(test); // Error because T inferred as {}

We fail to infer string for T because, upon seeing an argument of a type that has a generic signature (in this case <U>(b: string) => number) being passed to a parameter of a type with a non-generic signature (in this case (b: T) => any), we assume that the argument function uses its type parameter (in this case U) in a parameter position. Therefore, we first need to infer for U, and to do that we need to fix any inferences we have made for T so that we can infer to the type involving U. However, the type doesn't actually use U, so it ends up being a fruitless exercise that just causes T to become fixed with no inferences. Hence the {}.

So, it's behaving as intended and is effectively a design limitation of our inference algorithm.

@ahejlsberg ahejlsberg added Design Limitation Constraints of the existing architecture prevent this from being fixed and removed Bug A bug in TypeScript labels Apr 22, 2018
@SimonMeskens
Copy link
Author

@ahejlsberg So it's another instance of #22617?

I would really love to eventually get that one, as it's basically required for lifted type constructors, which is where I ran into this bug twice now. There's a lot of situations where you have something like

<U>(a: T) => Array<T>

The only way to properly type anything that passes through such lifting functions is by inferring the return type, but this issue is blocking it. I thought I found a workaround, but apparently, I just moved the issue elsewhere :)

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 31, 2018
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

4 participants