Variadic Tuple Types
A variadic tuple type places a spread element inside a tuple — like [first, ...rest] or [...T, last] — letting its length and element types vary with a type parameter so functions such as concat and curry stay precisely typed.
Learn Variadic Tuple Types in our free TypeScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn
💡 Real-World Analogy
Think of a train. A plain array is "some carriages" — you've forgotten which is the engine and which is the caboose. A variadic tuple is the precise consist: "engine, then these middle carriages, then the caboose." [first, ...rest] says "engine plus whatever follows"; [...rest, last] says "whatever comes before, then the caboose." Every carriage keeps its exact role and position, no matter how many sit in the middle.
1. Spreads Inside Tuple Types
A spread element inside a tuple type makes it variadic : [id: number, ...rest: T] is "a number, then however many elements T describes." The spread can sit at the start, middle, or end, mirroring how the array spread operator works at runtime — though a tuple type may contain at most one rest element.
2. Typing concat & Labeled Elements
The headline use is a concat whose return type is [...T, ...U] : it joins two tuples while keeping every element's type and position, so result[0] stays a number . Labeled tuple elements like [x: number, y: number] add names for readability — type-only, never at runtime.
3. Rest Parameters as Tuples & Currying
TypeScript types a function's ...args as a tuple , so variadic tuples are what make bind , currying , and partial application type-safe. Splitting a parameter tuple into a head and tail — [...H, ...T] — lets you fix some arguments now and supply the rest later, each part fully typed.
🎯 Your Turn
Build the runtime behind prepend<H, T>(head, tail): [H, ...T] — put head first, then spread the rest. Fill in the two blanks marked ___ , then run it.
Common Errors (and the fix)
- ❌ "A rest element must be last in a tuple type" in old TS — you put a spread before fixed elements. ✅ Modern TS allows leading/middle spreads; ensure you're on TS 4.0+.
- ❌ "A tuple type cannot be indexed with..." — you indexed past a variadic part's known positions. ✅ Only fixed positions have a precise type; the spread region is element-typed.
- ❌ Two rest elements — [...string[], ...number[]] is invalid. ✅ A tuple type may contain at most one rest element.
- ❌ Result widens to an array — you annotated the return as T[] . ✅ Return the variadic tuple [...T, ...U] to keep positions.
Pro Tips
- 💡 Label your tuple slots — [x: number, y: number] reads far better than two anonymous numbers.
- 💡 Combine with Parameters<F> to build typed pipe , compose , and partial utilities.
- 💡 Constrain spreads with T extends unknown[] so callers must pass an array-like tuple.
- 💡 Reach for variadic tuples whenever an array's positions matter — they're how you avoid losing type precision through a helper.
📚 Keep Learning
- 📖 TS 4.0 Release Notes — Variadic Tuple Types
- 📖 TS 4.0 — Labeled Tuple Elements
- 📖 Handbook — Tuple Types
Frequently Asked Questions
Mini-Challenge: pair() and swap()
No blanks this time — just a brief and a starting outline. Build the tuple-preserving helpers yourself, run them, and check your output against the example in the comments.
🎉 Lesson Complete
- ✅ A variadic tuple type spreads a type parameter inside a tuple
- ✅ [first, ...rest] and [...rest, last] prepend and append precisely
- ✅ A concat returning [...T, ...U] keeps every element's type and position
- ✅ Labeled tuple elements ( [x: number, y: number] ) document slots — type-only
- ✅ Rest parameters are tuples , which is how curry / partial get typed
- ✅ Next lesson: Advanced Utility Types
Practice quiz
A variadic tuple type is a tuple that includes:
- At least five elements
- Only optional elements
- A spread element referencing a type parameter
- No elements
Answer: A spread element referencing a type parameter. A spread inside a tuple type, like [first, ...rest], makes its length and contents vary with a type parameter.
The runtime equivalent of the type-level [...T, ...U] is:
- The array spread operator
- A for loop only
- Object.assign
- JSON.stringify
Answer: The array spread operator. Spreading both arrays into one ([...a, ...b]) mirrors the variadic tuple type exactly.
How many rest elements may a single tuple type contain?
- Zero
- Exactly two
- Unlimited
- At most one
Answer: At most one. A tuple type may have at most one rest element; [...string[], ...number[]] is an error.
Compared to (number | string)[], a variadic tuple [...T, ...U]:
- Forgets positions
- Keeps each element's type and position
- Is always shorter
- Cannot be returned
Answer: Keeps each element's type and position. A variadic tuple preserves exact types and positions, so result[0] can be known as number.
Labeled tuple elements like [x: number, y: number] are:
- Purely for readability, type-only
- Accessible at runtime as keys
- Required for variadic tuples
- A kind of union
Answer: Purely for readability, type-only. Labels document each slot for editors and readers but do not exist at runtime.
In TypeScript, a function's ...args rest parameter is typed as a:
- Union
- Record
- Tuple
- Promise
Answer: Tuple. Rest parameters are typed as a tuple, which is what makes typed bind, curry, and partial possible.
The spread element in a variadic tuple type may appear:
- Only at the end
- At the start, middle, or end
- Only at the start
- Never inside a tuple
Answer: At the start, middle, or end. Modern TypeScript allows the single rest element at the start, middle, or end.
[id: number, ...rest: T] where T is [string, boolean] describes:
The spread expands T's elements after the leading number, giving [id: number, string, boolean].
Parameters<(a: string, b: number) => void> is:
- string | number
Parameters extracts the argument types as a tuple — here [string, number].
Variadic tuples are most useful whenever an array's:
- Length is unknown
- Elements are all identical
- Positions matter
- Values are strings
Answer: Positions matter. They avoid losing type precision through helpers when each position's type matters.
Continue this course
- Previous: Function Types & this
- Next: Advanced Utility Types