Repository navigation
Implicit type conversion of tuple [...T[]] to array T[] #29311
Description
Activity
- addedBugA bug in TypeScriptA bug in TypeScriptDomain: check: Contextual TypesThe issue relates to contextual typesThe issue relates to contextual types
on Jan 8, 2019 In theory they're the same, but in practice the simplification we do deletes the fact that the type should be a tuple at all, which causes the error. So, because of that, it might be best not to perform the inlining so as to preserve the tupleness of the type.
We definitely want to keep the simplification of
[...T[]]toT[]. To fix the issue we should instead consider types that are array-like and have alengthproperty of a numeric literal type to be tuple-like. That would cause the contextual type to be tuple-like so we'd infer a tuple type for[0, 0].To fix the issue we should instead consider types that are array-like and have a length property of a numeric literal type to be tuple-like
And/or having numeric-named members (eg,
0: Thing), as is our internal tuplish criteria?The simplification at hand makes it hard to create a tuple constraint:
declare function test<T extends [...any[]]>(a: T): T const res1 = test([1, 2]) // ^? actual: number[], expected: [number, number]
There are different ways of dealing with this:
- the old weird trick of
T[] | [T] [T, ...T[]]- it doesn't allow an empty tuple[T?, ...T[]]- it might look OK at first glance but when passingT[K]through a mapped type to some other type, it will assume that it might beundefinedtoo, so this solution has some unintended caveatsconsttype params in 5.0+ - this implies constness which isn't always desirable- using the spread at argument position:
declare function test<T extends any[]>(a: [...T]): T. This works exactly as expected but requires moving the "hint" to the argument position
It seems that the most "complete" way of defining a tuple constraint using tuple types is...
[T, ...T[]] | []. It's quite cumbersome.- the old weird trick of
- locked as resolved and limited conversation to collaborators
on Oct 21, 2025
TypeScript Version: 3.3.0-dev.20190108
Search Terms: spread, rest, type conversion, tuple, array length
Code
Expected behaviour:
Expected
[...number[]]and[number, ...number[]]to have the same behaviour except that the latter requires at least one element in tuple.Actual behavior:
[...number[]]is implicitly converted tonumber[]with thelength: numberfield, that is incompatible withlength: 2Playground Link: 🔗
Related Issues: Haven't found anything about the same problem.