Why this produces an error "A rest element type must be an array type."?
type QWE<T extends [number, string]> = [boolean, ...T]
^^^^ the error is here
Why this produces an error "A rest element type must be an array type."?
type QWE<T extends [number, string]> = [boolean, ...T]
^^^^ the error is here
Before 3.0 we could not spread tuples or generic type arguments to a function and this had to be implemented. Similarly, rest in tuples currently only support arrays, nobody implemented the ability to spread other tuples into the rest of a given tuple, and I'm guessing implementing it would require significant effort and complexity.
To add a tuple at the end of another known tuple we can use the ability to spread a tuple tu a function and then extract the argument types as a tuple.
type ArgumentTypes<T extends (...a: any) => any> =
T extends (...a: infer A) => any ? A : never;
type QWE<T extends [number, string]> =
ArgumentTypes<(a: boolean, ...r: T) => void>
type R = QWE<[number, string]>
Adding the tuple at the start is more problematic, I believe there are some very unrecommended hacks that can achieve this using recursive type aliases. You can also define multiple conditions to support up to a number of elements in a tuple, but I would avoid it if possible
If someone can find it useful, this is a version of Titian's type, with an improvement covering some more cases:
type R = TupleUnshift<boolean, [number, string]> // [boolean, number, string]
type TupleUnshift<A, B extends [...any[]]> = ((a: A, ...r: ForcedTuple<B>) => void) extends (...a: infer R) => any ? R : never
type ForcedTuple<T> =
T extends [
infer A,
infer B,
infer C,
infer D,
infer E,
infer F,
infer G,
infer H,
infer I,
infer J,
infer K,
infer L,
infer M,
infer N,
infer O,
infer P,
infer Q,
infer R,
infer S,
infer T,
infer U,
infer V,
infer W,
infer X,
infer Y,
infer Z
]
?
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
: T
With TypeScript 4.0 variadic tuple types, adding an item I
to a tuple type T
gets much easier:
type Prepend<I, T extends unknown[]> = [I, ...T]
type Append<I, T extends unknown[]> = [...T, I]
type AddBetween<I, T extends unknown[], U extends unknown[]> = [...T, I, ...U]
type PrependTest = Prepend<boolean, [string, number]>
// [boolean, string, number]
type AppendTest = Append<boolean, [string, number]>
// [string, number, boolean]
type AddBetweenTest = AddBetween<boolean, [string], [number]>
// [string, boolean, number]