I'm trying to understand how infer
in TypeScript conditional types work. One thing I've noticed about infer
types in TypeScript is that they are defined to allow a rest element following another rest element. For example:
type A<T> = T extends [...infer X, 0, ...infer Y] ? [X, Y] : never;
type B = A<[1, 2]>; // B = [unknown[], unknown[]]
Interestingly, not only does TypeScript say this code is valid; the condition also succeeds, giving us X = unknown[]
and Y = unknown[]
. However, when we substitute in these inferred types, TypeScript gives us an error:
type C<T> = T extends [...unknown[], 0, ...unknown[]] ? true : false;
// Error: A rest element cannot follow another rest element. (1265)
Why does TypeScript require you to use infer
when using multiple rest elements, and why does it say that the type [1, 2]
contains the element 0
?
Even though they don't throw an error in an extends
clause, multiple rest types are not really supported. It is a known issue, currently considered a design limitation and unlikely to be fixed (emphasis mine):
This is unfortunately a design limitation as we have a very narrow heuristic that provides rudimentary support for inferring to multiple rest types in a tuple. It's not clear at this time whether this is something we want to extend. While a useful minimal repro, the example shown in the issue description doesn't illustrate a need that would be sufficient motivation to reevaluate this limitation. It would be helpful to understand the specific needs this issue is trying to address.