Tuples in rest parameters and spread expressions

TypeScript 3.0 adds support to multiple new capabilities to interact with function parameter lists as tuple types.TypeScript 3.0 adds support for:

Rest parameters with tuple types

When a rest parameter has a tuple type, the tuple type is expanded into a sequence of discrete parameters.For example the following two declarations are equivalent:

  1. declare function foo(...args: [number, string, boolean]): void;
  1. declare function foo(args_0: number, args_1: string, args_2: boolean): void;

Spread expressions with tuple types

When a function call includes a spread expression of a tuple type as the last argument, the spread expression corresponds to a sequence of discrete arguments of the tuple element types.

Thus, the following calls are equivalent:

  1. const args: [number, string, boolean] = [42, "hello", true];
  2. foo(42, "hello", true);
  3. foo(args[0], args[1], args[2]);
  4. foo(...args);

Generic rest parameters

A rest parameter is permitted to have a generic type that is constrained to an array type, and type inference can infer tuple types for such generic rest parameters. This enables higher-order capturing and spreading of partial parameter lists:

Example
  1. declare function bind<T, U extends any[], V>(f: (x: T, ...args: U) => V, x: T): (...args: U) => V;
  2. declare function f3(x: number, y: string, z: boolean): void;
  3. const f2 = bind(f3, 42); // (y: string, z: boolean) => void
  4. const f1 = bind(f2, "hello"); // (z: boolean) => void
  5. const f0 = bind(f1, true); // () => void
  6. f3(42, "hello", true);
  7. f2("hello", true);
  8. f1(true);
  9. f0();

In the declaration of f2 above, type inference infers types number, [string, boolean] and void for T, U and V respectively.

Note that when a tuple type is inferred from a sequence of parameters and later expanded into a parameter list, as is the case for U, the original parameter names are used in the expansion (however, the names have no semantic meaning and are not otherwise observable).

Optional elements in tuple types

Tuple types now permit a ? postfix on element types to indicate that the element is optional:

Example
  1. let t: [number, string?, boolean?];
  2. t = [42, "hello", true];
  3. t = [42, "hello"];
  4. t = [42];

In —strictNullChecks mode, a ? modifier automatically includes undefined in the element type, similar to optional parameters.

A tuple type permits an element to be omitted if it has a postfix ? modifier on its type and all elements to the right of it also have ? modifiers.

When tuple types are inferred for rest parameters, optional parameters in the source become optional tuple elements in the inferred type.

The length property of a tuple type with optional elements is a union of numeric literal types representing the possible lengths.For example, the type of the length property in the tuple type [number, string?, boolean?] is 1 | 2 | 3.

Rest elements in tuple types

The last element of a tuple type can be a rest element of the form …X, where X is an array type.A rest element indicates that the tuple type is open-ended and may have zero or more additional elements of the array element type.For example, [number, …string[]] means tuples with a number element followed by any number of string elements.

Example
  1. function tuple<T extends any[]>(...args: T): T {
  2. return args;
  3. }
  4. const numbers: number[] = getArrayOfNumbers();
  5. const t1 = tuple("foo", 1, true); // [string, number, boolean]
  6. const t2 = tuple("bar", ...numbers); // [string, ...number[]]

The type of the length property of a tuple type with a rest element is number.