Type modern syntax

INPUT · Slides

Type rest parameters

01 / 06

The type of "everything else"

A rest parameter (...scores) lets the caller pass as many as they like. In TypeScript you give it an array type.

...scores: number[] means "as many as you like, all numbers".

function sum(...scores: number[]): number {  let total = 0;  for (const s of scores) {    total += s;  }  return total;}console.log(sum(80, 65, 92));

Result

237

02 / 06

Mix a string in and it stops you

You declared number[], so a string gets caught. When anything can be passed, a type is especially reassuring.

function sum(...scores: number[]): number {  let total = 0;  for (const s of scores) { total += s; }  return total;}console.log(sum(80, "65", 92));

Result

Type error: Argument of type 'string' is not assignable to parameter of type 'number'.

03 / 06

Mix it with ordinary parameters

The rest parameter is always last. Putting ordinary parameters before it and catching the rest is a pattern you will see a lot.

function log(level: string, ...messages: string[]): void {  for (const m of messages) {    console.log(`[${level}] ${m}`);  }}log("INFO", "started", "ready");

Result

[INFO] started
[INFO] ready

04 / 06

It still works with zero arguments

A rest parameter does not error if you pass none at all — it just receives an empty array [].

"As many as you like" includes "zero", so keep that in mind.

function sum(...scores: number[]): number {  let total = 0;  for (const s of scores) {    total += s;  }  return total;}console.log(sum());

Result

0

05 / 06

Only array and tuple types fit

Because the caller can pass any number of them, a rest parameter can only be typed as "a sequence of things": an array type like number[], or a tuple type like [string, number].

An object shape ({ ... }) does not fit directly. To take several objects, wrap the object shape in an array, like ...list: { name: string }[].

function names(...people: { name: string }[]): string[] {  return people.map((p) => p.name);}console.log(names({ name: "Yui" }, { name: "Kei" }));

Result

["Yui", "Kei"]

06 / 06

The same syntax in an arrow function

Rest parameters look exactly the same whether you write function or an arrow function: (...paramName: type[]) => ....

const total = (...nums: number[]): number => {  return nums.reduce((a, b) => a + b, 0);};console.log(total(1, 2, 3));

Result

6