Skip to content

Generic with type inference in conditional type not evaluated into definitive type #42636

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
turtleflyer opened this issue Feb 4, 2021 · 3 comments Β· Fixed by #42747
Closed
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue

Comments

@turtleflyer
Copy link

turtleflyer commented Feb 4, 2021

Bug Report

πŸ”Ž Search Terms

generic conditional type inference not evaluated

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about generic and conditional types

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

type SubGuard<A, X extends [A]> = X;

type IsSub<M extends any[], S extends any[]> = M extends [
  ...SubGuard<M[number], infer B>,
  ...S,
  ...any[]
]
  ? B
  : never;

type E0 = IsSub<[1, 2, 3, 4], [2, 3, 4]>; //  Evaluated: type E0 = [1, 2, 3, 4] extends [...infer B, 2, 3, 4, ...any[]] ? B : never

type E1 = [1, 2, 3, 4] extends [...infer B, 2, 3, 4, ...any[]] ? B : never; // type E1 = unknown[]

declare let v0: E0;
declare let v1: E1;
declare let v2: unknown[];

  v0 = v1 = v2 = v1;
// ^ Type 'unknown[]' is not assignable to type 'IsSub<[1, 2, 3, 4], [2, 3, 4]>'.(2322)

v1 = v2 = v0; // Ok

πŸ™ Actual behavior

The generic type being provided with correct parameters IsSub<[1, 2, 3, 4], [2, 3, 4]> appears to get evaluated into a conditianal type literal [1, 2, 3, 4] extends [...infer B, 2, 3, 4, ...any[]] ? B : never

πŸ™‚ Expected behavior

If such a generic has an error in syntax or faces some limitation in the use, the compiler should raise an exception. If it is correct (it looks correct) it must be evaluated into a definitive type, e.g. unknown[]. In contrast, if we change generic:

type IsSub<M extends any[], S extends any[]> = M extends [
  ...SubGuard<M[number], infer B>,
  ...S
]
  ? B
  : never;

it gives us:

type E0 = IsSub<[1, 2, 3, 4], [2, 3, 4]>; //  Evaluated: type E0 = [1]

that is expected.


One more inconsistency in the example:

If we add:

declare let v3: never;

v3 = v0;

the compiler shows an error:

Type 'IsSub<[1, 2, 3, 4], [2, 3, 4]>' is not assignable to type 'never'.
  Type '[M[number]]' is not assignable to type 'never'.(2322)

where we can see type [M[number]] which is absurd since M is not in the context and is the name of a variable in the original generic type IsSub<M extends any[], S extends any[]>.

If we substitute M with [1, 2, 3, 4] it still does not answer what actual type we have:

declare let v4: [[1, 2, 3, 4][number]];

v0 = v4; // Error
v4 = v0; // Ok

Playground

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Feb 5, 2021
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 4.3.0 milestone Feb 5, 2021
@ahejlsberg
Copy link
Member

It's definitely wrong that E0 remains a deferred conditional type. Looks like a combined type mapper we're creating in getConditionalType isn't properly instantiating [M[number]] into [1 | 2 | 3 | 4].

@ahejlsberg ahejlsberg added Bug A bug in TypeScript and removed Needs Investigation This issue needs a team member to investigate its status. labels Feb 9, 2021
@ahejlsberg
Copy link
Member

Smaller repro:

type Constrain<T extends C, C> = unknown;

type Foo<A> = A extends Constrain<infer X, A> ? X : never;

type T0 = Foo<string>;  // A but should be string

The issue is that the constraint A conferred on X through the Constrain<infer X, A> type reference isn't properly instantiated to string.

@turtleflyer
Copy link
Author

type T0 = Foo<string>; // A but should be string

In version 3.3.3333 it gives us X instead A.
Playground

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants