runtime.boot

Full Stack Systems
Production Mindset

CodeWithMihir

Engineering thoughtful products from interface to infrastructure.

CodeWithMihir

TypeScript Tutorial

TypeScript Rest Parameters Explained with Examples

Learn how rest parameters work in TypeScript, including typed rest arrays, number arguments, string arguments, tuples, and callback examples.

Welcome back! I am Mihir, and in this lesson we will learn rest parameters in TypeScript.

Rest parameters let a function accept any number of arguments.


What is a Rest Parameter?

Use ... before the parameter name.

function printNames(...names: string[]): void {
  names.forEach((name) => console.log(name));
}

Now you can call:

printNames("Mihir");
printNames("Mihir", "Aarav", "Riya");

Inside the function, names is a string[].


Rest Parameters Must Be Arrays

This is the correct type:

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

Call it like this:

sum(10, 20, 30);

Invalid:

sum(10, "20", 30);

Every argument must be a number.


Rest Parameter Must Be Last

Rest parameters collect the remaining arguments, so they must come last.

function logMessages(prefix: string, ...messages: string[]): void {
  messages.forEach((message) => console.log(`${prefix}: ${message}`));
}

This works:

logMessages("INFO", "Started", "Loaded", "Finished");

The first argument is prefix. The rest go into messages.


Rest Parameters with Union Types

function printValues(...values: Array<string | number>): void {
  values.forEach((value) => console.log(value));
}

This accepts strings and numbers:

printValues("id", 101, "score", 95);

Invalid:

printValues(true);

Boolean is not part of the union.


Rest Parameters with Tuples

You can use tuple types when the remaining arguments have a specific shape.

function createUser(...args: [name: string, age: number]): void {
  const [name, age] = args;
  console.log(`${name} is ${age} years old`);
}

Call:

createUser("Mihir", 25);

Invalid:

createUser(25, "Mihir");

The tuple order matters.


Rest Parameters vs Spread Syntax

Rest collects arguments:

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

Spread expands an array:

const scores = [10, 20, 30];

sum(...scores);

Same ... symbol, different direction.


Rest Parameters in Callbacks

Rest parameters can be used in function types too.

type Logger = (...messages: string[]) => void;

const logger: Logger = (...messages) => {
  messages.forEach((message) => console.log(message));
};

This describes a function that accepts any number of string messages.


Common Mistake: Using any[]

Avoid this:

function logEverything(...items: any[]): void {
  console.log(items);
}

Prefer a safer type:

function logValues(...items: Array<string | number | boolean>): void {
  console.log(items);
}

Use unknown[] if values are truly unknown and must be checked first.


Quick Reference Summary

ConceptExample
String rest...names: string[]
Number rest...numbers: number[]
Must be lastprefix: string, ...items: string[]
Union rest...(string | number)[]
Tuple rest...args: [string, number]
Function type(...messages: string[]) => void

Practice

Create a function that calculates an average:

function average(...scores: number[]): number {
  const total = scores.reduce((sum, score) => sum + score, 0);
  return total / scores.length;
}

console.log(average(90, 85, 100));

Try passing a string and see what TypeScript says.


What You've Learned

You now understand:

  • What rest parameters are
  • How to type rest parameters as arrays
  • Why rest parameters must be last
  • How union rest parameters work
  • How tuple rest parameters work
  • The difference between rest and spread
  • How to type rest parameters in function types

What's Next?

In the next lesson, we will learn Function Type Expressions in TypeScript.

We will describe function shapes using reusable types.


Need Help?

  • Have questions, confusion, or want to know more? Contact me

Rest parameters are perfect when a function has one job but flexible input length.