To simplify the code, you can utilize variadic tuple types in TypeScript 4.0 instead of creating an additional type abstraction:
type T3 = ["g", "h", "i"]
type Concatenated = [...T1, ...T2, ...T3] // ["a", "b", ..., "h", "i"]
If you still require a separate Concat
type, you can make use of recursive conditional types in TypeScript 4.1, which is stricter than Aleksey's solution:
// separate initial and recursive type constructor
type Concat<T extends unknown[][]> = ConcatRec<T>
type ConcatRec<T extends unknown[]> = T extends [infer I, ...infer R] ?
I extends unknown[] ? [...I, ...ConcatRec<R>] : never
: T
type R1 = Concat<[T1, T2, T3]>; // ["a", "b", "c", ... , "i"]
type R2 = Concat<["foo"]>; // now errors properly
You can combine this type with Array.prototype.concat
as shown below:
function concat<T extends [unknown, ...unknown[]][]>(...t: T): Concat<T> {
return [].concat(...t as any) as any
}
const result = concat([1, "a", 3], [true, 5, new Date()])
// const res: [number, string, number, boolean, number, Date]
Check out the Live code sample on Playground