Description
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