Rest Parameters (...)
Rest Parameters (...)
Level 4 — Functions A syntax that allows a function to accept an infinite number of arguments as an array. In TypeScript, Rest Parameters must always be typed as an Array.
1. Prerequisites
- Function Types — The context where rest parameters are used.
- Arrays & Tuples — The type you must apply to a rest parameter.
2. Term Category
TypeScript Core Syntax (Variadic Rest Parameter Typing): Rest parameters (...args: T[]) capture variable numbers of trailing function arguments into a type-safe array or tuple.
3. Explanation
Environment Context
- Compile-Time
(1) Design Motivation — "Why did we design this?"
Sometimes you want a function to take an arbitrary number of arguments. For example, Math.max(1, 5, 10, 2) can take four numbers, or it can take four hundred numbers.
In ES6 JavaScript, we use the Rest operator (...) to gather all those loose arguments into a single Array inside the function.
In TypeScript, because those arguments are gathered into an Array, you MUST type the Rest parameter as an Array.
(2) Typing the Rest Parameter
You add the ... before the parameter name, and you type it as type[].
// `numbers` will be an array of numbers
function sumAll(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);
}
// ✅ Valid: passing 3 loose arguments
sumAll(10, 20, 30);
// ✅ Valid: passing 0 arguments (numbers will be `[]`)
sumAll();
(3) Mixing Regular and Rest Parameters
Just like optional parameters, the Rest parameter must be the very last parameter in the list. It gathers up whatever is "rest" (left over).
function buildTeam(captain: string, ...members: string[]) {
console.log(`Captain: ${captain}, Team: ${members.join(", ")}`);
}
buildTeam("Alice", "Bob", "Charlie", "Dave");
// captain = "Alice"
// members = ["Bob", "Charlie", "Dave"]
4. Common Mistakes & Pitfalls
Mistake 1: Not typing it as an Array
The mistake: A developer writes: function printAll(...items: string) {}
Why it's wrong: The developer thinks "items are strings, so I type it as a string". But the ... operator literally creates a JavaScript Array containing all the arguments. If you type it as a string, TypeScript will throw an error because a string is not an Array.
Golden Rule: A Rest parameter MUST be typed as an Array (type[] or Array<type>) or a Tuple.
Mistake 2: Annotating Rest Parameters as Non-Array Types
The mistake: Writing function sum(...nums: number) (TS1014).
Why it's wrong: Rest parameters gather trailing arguments into an array. Their type annotation MUST be an array or tuple type (number[] or Array<number>).
Incorrect:
// function sum(...nums: number) {} // ❌ A rest parameter must be of an array type
Fix:
function sum(...nums: number[]) {} // Correct array annotation
Mistake 3: Placing Rest Parameters Before Other Parameters
The mistake: Writing function log(...tags: string[], msg: string).
Why it's wrong: Rest parameters MUST be the last parameter in function parameter lists.
Incorrect:
// function log(...tags: string[], msg: string) {} // ❌ A rest parameter must be last
Fix:
function log(msg: string, ...tags: string[]) {} // Correct position
5. Practice Exercises
Exercise 1: Typing Variadic Functions with Rest Parameters
Scenario:
Create a sumNumbers utility function accepting a variable number of numeric arguments.
Requirements:
- Annotate rest parameter
...numbers: number[].
Answer
Implementation
function sumNumbers(...numbers: number[]): number {
return numbers.reduce((acc, curr) => acc + curr, 0);
}
const total1 = sumNumbers(10, 20, 30); // 60
const total2 = sumNumbers(5, 15, 25, 35, 45); // 125
Technical Explanation
- Rest parameters (
...numbers: number[]) gather all remaining call arguments into a type-safe array. - Must be the last parameter in the function declaration.
- Enforces element type consistency across variable argument lists.
Exercise 2: Tuple Rest Parameters for Leading Parameter Typing
Scenario: Use tuple rest parameters to require a string action name followed by a variable tuple of payload parameters.
Requirements:
- Annotate tuple rest parameters
...args: [action: string, ...data: number[]].
Answer
Implementation
type ActionTuple = [action: string, ...payload: number[]];
function dispatchAction(...[action, ...data]: ActionTuple) {
console.log(`Action: ${action}, Data Count: ${data.length}`);
}
dispatchAction("ADD", 10, 20, 30);
Technical Explanation
- Rest elements in tuples (
[string, ...number[]]) allow defining exact leading argument types followed by dynamic trailing arguments. - Enables type-safe tuple destructuring in variadic function signatures.
- Advanced parameter typing pattern.
Exercise 3: Spreading Readonly Tuples into Rest Parameters
Scenario:
Spread a const tuple into a function expecting rest parameters using as const.
Requirements:
- Pass
[10, 20]tuple into function using spread operator...args.
Answer
Implementation
function multiply(a: number, b: number): number {
return a * b;
}
const tuple = [5, 4] as const; // Inferred as readonly [5, 4] tuple
// Valid spread invocation:
const result = multiply(...tuple);
Technical Explanation
- Spreading a mutable array (
number[]) into positional arguments fails because array length is unbounded. - Marking the tuple
as constinforms TypeScript of its exact fixed length (2 elements). - Allows type-safe parameter spreading into positional arguments.
6. Related Terms
- Arrays & Tuples — The type required for Rest parameters.
- Function Types — The parent topic.
7. Key Takeaways
- Rest Parameters (
...args) allow a function to accept an infinite number of positional arguments. - Under the hood, JS gathers these arguments into an Array.
- Therefore, in TypeScript, you MUST type the Rest parameter as an array (e.g.,
...args: string[]). - The Rest parameter must always be the very last parameter in the function signature.