`Array<T>` und `T[]` tragen keine Längeninformation auf Typebene — eine Funktion für 3-Vektoren kann zur Compile-Zeit keinen 2-Vektor ablehnen. Der endrekursive `Tuple<T, N, R>`-Builder sammelt Elemente in `R`, bis `R['length']` literal `N` entspricht, und gibt dann `R` selbst zurück — ein Tupel-Typ mit fester Länge. Das Default-Argument `R extends T[] = []` ist der Rekursions-Seed und der Grund, warum Aufrufer nur `Tuple<T, N>` schreiben. TypeScript begrenzt rekursive Instanziierungen auf 1000 — bis dahin funktioniert das; darüber braucht man eine Divide-and-Conquer-Verdopplung.
type Tuple<T, N extends number, R extends T[] = []> =R['length'] extends N ? R : Tuple<T, N, [...R, T]>;type Vec3 = Tuple<number, 3>; // [number, number, number]type RGB = Tuple<0 | 128 | 255, 3>; // strictly 3 channelsfunction dot<N extends number>(a: Tuple<number, N>,b: Tuple<number, N>): number {return a.reduce((s, x, i) => s + x * b[i], 0);}const v: Vec3 = [1, 2, 3];const w: Vec3 = [4, 5, 6];dot(v, w); // 32// dot(v, [1, 2] as const);// ^^^^^^^^^^^^^^^^^// Source has 2 element(s) but target requires 3.