TypeScript Building Type Utilities
A type utility is a generic type alias that computes a new type from its input. Building one in small steps, with an assignment proving each step, keeps every stage honest.
Reading one position with an indexed access
The indexed access Pair[0] reads the type stored at position 0. The assignment accepts exactly that type.
type Pair = ['pen', 3];
type First = Pair[0];
const firstLabel: First = 'pen';
console.log(firstLabel);A first attempt reads only the first member
This attempt builds the union from position 0 alone. The second member is refused, and the refusal is the evidence that the attempt is too narrow.
type FirstTryUnion<T extends readonly unknown[]> = T[0];
type OnlyFirst = FirstTryUnion<['alpha', 'beta']>;
const second: OnlyFirst = 'beta';
console.log(second);TupleToUnion reads every member with an index of number
Indexing with number reads all positions at once, so the computed type is the union of the member types. Assignments accept a string member and the numeric member.
type TupleToUnion<T extends readonly unknown[]> = T[number];
type Member = TupleToUnion<['alpha', 'beta', 7]>;
const wordMember: Member = 'beta';
const numberMember: Member = 7;
console.log(wordMember);
console.log(numberMember);Length reads the count from a tuple
A tuple type carries its member count as a literal length type. Length reads that member, and the assignment accepts only the count 4.
type Length<T extends readonly unknown[]> = T['length'];
type StepCount = Length<['read', 'check', 'build', 'ship']>;
const stepCount: StepCount = 4;
console.log(stepCount);Example
type TupleToUnion<T extends readonly unknown[]> = T[number];
type Length<T extends readonly unknown[]> = T['length'];
type Stages = ['draft', 'review', 'publish'];
type Stage = TupleToUnion<Stages>;
type StageCount = Length<Stages>;
const current: Stage = 'review';
const total: StageCount = 3;
console.log(current);
console.log(total);Key points
- An indexed access type reads a member type out of another type, such as the element type at a tuple position.
- Indexing with number reads the union of every element type in a tuple type.
- A first attempt that reads only position 0 proves too little, and a refused assignment exposes the gap.
- Reading the length member of a tuple type gives its literal member count.
- Each build step is verified by assigning values the computed type must accept.
In this example, TupleToUnion and Length both read from one Stages tuple, and the assignments prove the union holds the stage names while the count holds only the literal 3.
Note
An array type has length number, while a tuple type has a literal length, so Length is stated for tuples.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท TypeScript Playground
Exercise
What does indexing a tuple type with number produce?