Skip to content
TypeScript ts functions 4 min read

Rest Parameters

A rest parameter gathers an unbounded list of trailing arguments into a single array, letting a function accept a variable number of inputs. TypeScript types the rest parameter as an array (or tuple), checks every argument against the element type, and supports spreading typed tuples back into calls. This page covers the syntax and ordering rules, typing the collected array, variadic tuple types, and how rest parameters power precise wrapper functions.

Declaring a rest parameter

Prefix the final parameter with ... and give it an array type. Every extra argument the caller passes is collected into that array.

function sum(...numbers: number[]): number {
  return numbers.reduce((total, n) => total + n, 0);
}

sum();           // 0
sum(1, 2, 3);    // 6
sum(1, 2, 3, 4); // 10

Inside the body, numbers is a number[], so all the usual array methods are available. Each argument at the call site is checked against the element type — sum(1, "2") is a compile error.

The rest parameter must come last

A function may have only one rest parameter, and it must be the final parameter. Required and optional parameters come before it.

function logEvent(level: string, ...messages: string[]): void {
  console.log(`[${level}]`, ...messages);
}

logEvent("info", "server started", "on port 3000");

// ❌ Error: A rest parameter must be last in a parameter list.
function bad(...items: number[], label: string) {}

Here level is a fixed first argument and everything after it is collected into messages.

Typing the collected arguments

The element type of the rest array dictates what each argument may be. Use a union to accept mixed types, or unknown[] when the inputs are genuinely heterogeneous and you will narrow them later.

function joinPath(...segments: (string | number)[]): string {
  return segments.join("/");
}

joinPath("api", "users", 42); // "api/users/42"

Because the elements are typed string | number, the compiler rejects joinPath("api", true) while allowing both strings and numbers.

Variadic tuple types

A rest parameter can be typed as a tuple rather than a plain array, which lets you describe a fixed prefix followed by a variable tail. This is the foundation of variadic tuple types in modern TypeScript.

type StringThenNumbers = [name: string, ...scores: number[]];

function record(...args: StringThenNumbers) {
  const [name, ...scores] = args;
  return { name, average: scores.reduce((a, b) => a + b, 0) / scores.length };
}

record("Ada", 90, 85, 95); // { name: "Ada", average: 90 }

The first argument is required and must be a string; the rest are numbers. Tuple labels (name:, scores:) are documentation only but improve editor hints.

Variadic tuples let you write fully typed wrappers around other functions. Combined with Parameters<T>, you can forward an arbitrary argument list without losing type safety.

Spreading typed tuples into calls

The mirror image of a rest parameter is the spread at a call site. When you spread a tuple, TypeScript matches its elements positionally against the function’s parameters.

function setPoint(x: number, y: number, z: number) {
  return { x, y, z };
}

const coords: [number, number, number] = [1, 2, 3];
setPoint(...coords); // ✅ matches three parameters

const partial: [number, number] = [1, 2];
// ❌ Error: Expected 3 arguments, but got 2.
setPoint(...partial);

A spread of a plain number[] (unknown length) would not satisfy fixed parameters — only a tuple of the right length does.

Rest parameters vs. the arguments object

The legacy arguments object is untyped and not a real array. Rest parameters supersede it entirely: they are typed, are genuine arrays, and work in arrow functions (which have no arguments).

FeatureRest parameterarguments
TypedYesNo (IArguments)
Real arrayYesNo (array-like)
Works in arrow functionsYesNo
Excludes named parametersYesNo (includes all)

Always prefer rest parameters in TypeScript; avoid arguments entirely.

Best Practices

  • Use a rest parameter to accept a variable-length list of trailing arguments.
  • Keep the rest parameter last; a function may have only one.
  • Type the rest array element precisely — a union is fine, unknown[] when you must, never any[].
  • Use variadic tuple types to model a fixed prefix plus a variable tail.
  • Spread tuples (not loose arrays) when forwarding a fixed argument list.
  • Combine rest parameters with Parameters<T> to build type-safe wrapper functions.
  • Never use the legacy arguments object; rest parameters replace it cleanly.
Last updated June 29, 2026
Was this helpful?