Concepto 11 de 12
Tuplas variádicas
Las tuplas son la única estructura de datos con longitud a nivel de tipos, lo que las convierte en su único contador. Toda la aritmética a nivel de tipos que verás es contar elementos de una tupla disfrazado.
Las expansiones concatenan
type A = [1, 2] type B = [3, 4] type Joined = [...A, ...B] // [1, 2, 3, 4] type Prefixed = [0, ...A] // [0, 1, 2] type Len = Joined['length'] // 4 — a numeric literal type
Para una tupla de longitud fija, `length` es un literal numérico y no `number`. Ese único hecho hace posible la aritmética: construye una tupla del tamaño correcto y luego lee su longitud.
Sumar es concatenar, restar es emparejar
type Build<N extends number, Acc extends unknown[] = []> = Acc['length'] extends N ? Acc : Build<N, [...Acc, unknown]> type Add<A extends number, B extends number> = [...Build<A>, ...Build<B>]['length'] type Sub<A extends number, B extends number> = Build<A> extends [...Build<B>, ...infer Rest] ? Rest['length'] : never
Construir una tupla suma; desarmarla resta. El acumulador contiene `unknown` porque su contenido es irrelevante — es una cuenta de marcas, no una colección de nada.
Un elemento rest no tiene que ir al final
type Last<T> = T extends readonly [...unknown[], infer L] ? L : never type Init<T> = T extends readonly [...infer I, unknown] ? I : never
Un patrón de tupla admite exactamente un elemento rest, y puede ir al principio. Así se llega al final de una tupla sin contar.
El error más común
// Intent: subtract. type Sub<A extends number, B extends number> = [...Build<A>, ...Build<B>]['length'] // That is addition with a different name — concatenating // can only ever make the tuple longer.
La resta tiene que desarmar una tupla, lo que exige emparejar patrones en vez de construir. Si tu tipo aritmético solo expande, solo puede sumar.
Para recordar
La longitud de tupla es el único número con el que el sistema de tipos sabe contar. Construye para sumar, desestructura para restar, y cuenta con el límite de recursión sobre el millar.