Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Rest element destructuring is a syntactic mechanism that collects the remaining, unassigned enumerable properties of an object or the remaining elements of an iterable into a newly allocated object or array during a destructuring assignment. In TypeScript, the type of the rest element is strictly evaluated and inferred based on the source structure, preserving type safety for the extracted subset.

Array and Tuple Destructuring

When destructuring an array or tuple, the rest element (...) captures all subsequent items into a new array. TypeScript infers the type of the rest element based on the source iterable.
// Array destructuring
const numbers: number[] = [1, 2, 3, 4, 5];
const [first, second, ...remainingNumbers] = numbers;
// remainingNumbers is inferred as number[]

// Tuple destructuring
const tuple: [string, boolean, number, number] = ["test", true, 42, 84];
const [str, flag, ...restTuple] = tuple;
// restTuple is inferred as [number, number]
If the source is a strongly typed tuple, TypeScript preserves the exact length and types of the remaining elements as a new tuple type. If the source is a standard array, the rest element is typed as an array of the source’s element type.

Object Destructuring

In object destructuring, the rest element collects all enumerable own properties that have not been explicitly destructured. TypeScript computes the type of the rest object by stripping the explicitly destructured properties from the source type.
interface User {
  id: string;
  name: string;
  age: number;
  isActive: boolean;
}

const user: User = { id: "abc", name: "Alice", age: 30, isActive: true };

const { id, name, ...restUser } = user;
// restUser is inferred as { age: number; isActive: boolean; }
Crucially, TypeScript’s internal type computation for rest elements is not strictly equivalent to the Omit utility type. When evaluating a rest element against a union type, TypeScript distributes the rest operation over the union members, preserving the union structure. In contrast, Omit does not distribute over unions and instead resolves them to a single object type. This ensures the inferred type strictly matches the runtime behavior of the rest operator across complex type structures.

Explicit Typing

While TypeScript’s type inference handles most scenarios, you can explicitly declare the type of the destructured variables, including the rest element, by typing the entire binding pattern.
// Explicitly typing a tuple with a rest element
const [a, ...b]: [number, ...string[]] = [1, "two", "three"];
// 'a' is explicitly number
// 'b' is explicitly string[]

// Explicitly typing an object binding pattern
const { x, ...rest }: { x: number; y: string; z: boolean } = { x: 1, y: "hello", z: true };
// 'x' is number
// 'rest' is { y: string; z: boolean }

Structural Constraints

The TypeScript compiler enforces strict structural rules regarding rest elements in binding patterns:
  1. Terminal Position: The rest element must always be the final element in the destructuring pattern. Placing a comma or another binding after the rest element results in a syntax error.
  2. Single Rest Element: Only one rest element is permitted per destructuring level.
  3. No Trailing Commas: A trailing comma is not allowed immediately following a rest element.
// Invalid Syntax Examples
const [...rest, last] = [1, 2, 3]; 
// TS1014: A rest element must be last in a destructuring pattern.

const { a, ...rest, b } = { a: 1, b: 2, c: 3 }; 
// TS1014: A rest element must be last in a destructuring pattern.
Master TypeScript with Deep Grasping Methodology!Learn More