I have a library where I added this function length
:
const length = <
T extends AnyArray,
S extends LengthComparison,
R extends ToTuple<ElementOf<T>, ExtractLength<S>>
>(
array: T,
condition: S
): array is R extends T ? R : never
The whole implementation is added to this Playground
When I check it in Playground, *.d.ts
will look like:
declare const length: <T extends AnyArray, S extends `>= ${number}`, R extends _ToTuple<ElementOf<T>, ExtractLength<S>, []>>(array: T, condition: S) => array is R extends T ? R : never;
However if I compile it with tsc
, I will see a different picture:
declare const length: <T extends AnyArray, S extends `>= ${number}`, R extends ExtractLength<S> extends infer T_1 ? T_1 extends ExtractLength<S> ? T_1 extends never ? never : ElementOf<T>[] : never : never>(array: T, condition: S) => array is R extends T ? R : never;
So the generic constrain for R
is inlined and the implementation looks definitely wrong.
How come? What am I doing wrong?
Additional information:
- npm package – https://github.com/Beraliv/ttuple
- Playground with
ttuple
– https://tsplay.dev/mpnZbw - Playground with completely different result – https://tsplay.dev/mAKkkw
- Twitter thread, where I explained how I found it – https://twitter.com/beraliv/status/1553833952418439170