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.

The ... token in TypeScript represents two distinct operations depending on its syntactic context: Spread syntax, which expands an iterable or object into discrete elements, and Rest syntax, which collects multiple discrete elements into a single array or object. TypeScript enforces strict type-checking on both operations, inferring resulting types based on the source structures and the presence of literal or contextual type assertions.

Spread Syntax (Expansion)

In value space, spread syntax unpacks elements from an existing structure into a new structure. Array and Tuple Spread When spreading arrays or tuples into a standard array literal, TypeScript infers a general array type (T[]) composed of a widened union of all element types. It does not automatically preserve fixed lengths or positional types. To preserve exact lengths, positional types, and literal types (creating a concatenated tuple type), an as const assertion or a contextual tuple type must be applied.
const dynamicArray: number[] = [1, 2];
const tuple = [3, 4] as const;

// Type: number[] (The union of number | 3 | 4 | 5 is eagerly widened to number)
const mergedArray = [...dynamicArray, ...tuple, 5]; 

// Type: readonly [3, 4, 5]
const mergedTuple = [...tuple, 5] as const; 
Object Spread When spreading objects, TypeScript computes a type with directional overwrite semantics. Properties from objects spread later in the expression overwrite properties of the same name from earlier objects. TypeScript intentionally strips readonly modifiers when spreading objects into new literals.
const objA: { readonly a: number; b: string } = { a: 1, b: "string" };
const objB = { b: true, c: 3 };

// Type: { a: number; b: boolean; c: number; } ('a' is no longer readonly)
const mergedObj = { ...objA, ...objB }; 
Note: Spreading objects in TypeScript intentionally bypasses excess property checks that normally apply to object literals.

Rest Syntax (Collection)

Rest syntax performs the inverse operation, condensing remaining elements or properties into a single binding. It must always be the final element in a destructuring assignment or function signature. Function Rest Parameters In function signatures, a rest parameter collects trailing arguments into an array. TypeScript requires rest parameters to be typed as an array (T[]) or a tuple type.
// Typed as a generic array
function sum(...numbers: number[]): number { /* ... */ }

// Typed as a variadic tuple (requires at least one string, followed by booleans)
function log(prefix: string, ...flags: [string, ...boolean[]]): void { /* ... */ }
Destructuring Rest Elements When destructuring arrays or objects, the rest operator infers a new type containing only the properties or elements that were not explicitly extracted.
const sourceObj = { id: 1, name: "TS", active: true };

// 'rest' Type: { name: string; active: boolean; }
const { id, ...rest } = sourceObj; 

const sourceTuple: [number, string, boolean] = [1, "A", true];

// 'tail' Type: [string, boolean]
const [head, ...tail] = sourceTuple; 

Type Space Mechanics

TypeScript also allows the ... operator directly within type annotations to manipulate tuple types. This is known as Variadic Tuple Types. It allows types to be dynamically constructed by spreading other tuple types or generic type parameters.
type Strings = [string, string];
type Numbers = number[];

// Type: [boolean, string, string, ...number[]]
type CombinedTuple = [boolean, ...Strings, ...Numbers];

// Generic variadic tuple
type Push<T extends any[], V> = [...T, V];
// Type: [string, number, boolean]
type Result = Push<[string, number], boolean>; 
Master TypeScript with Deep Grasping Methodology!Learn More