Optional, Default & Rest Parameters

beginner functions parameters

In simple language, sometimes we don’t want every parameter to be mandatory. TypeScript gives us three tools for that: optional (?), default values, and rest (...).

Optional parameters

Add a ? after the name and the parameter becomes optional. Inside the function, its type becomes T | undefined, so we still need to handle the “not passed” case.

function greet(name: string, title?: string): string {
  // title is string | undefined here
  return title ? `${title} ${name}` : name;
}

greet("Manish");         // OK
greet("Manish", "Dr.");  // OK

Rule: optional parameters must come AFTER required ones. function bad(a?: string, b: number) is a compile error.

Default parameters

A default value makes the parameter optional AND gives it a fallback. Now we don’t need the | undefined check inside.

function greet(name: string, title: string = "Mr."): string {
  return `${title} ${name}`; // title is just string, never undefined
}

greet("Manish");           // "Mr. Manish"
greet("Manish", "Dr.");    // "Dr. Manish"
greet("Manish", undefined); // "Mr. Manish" — undefined triggers default

Defaults can be after required params too, and they can even reference earlier parameters. They don’t need to be at the end IF the call site passes undefined explicitly.

Rest parameters

When we don’t know how many arguments will come in, we collect them into an array with .... Think of it like the opposite of spread.

function sum(...nums: number[]): number {
  return nums.reduce((a, b) => a + b, 0);
}

sum(1, 2, 3);       // 6
sum();              // 0
sum(...[1, 2, 3]);  // 6 — spread back in

Rest must be the last parameter, and its type is always an array (or tuple).

Tuples in rest — the powerful trick

We can type rest params as a tuple to enforce specific positions. Super useful for things like event emitters.

type EventArgs = [event: string, payload: object];

function emit(...args: EventArgs) {
  const [event, payload] = args;
  console.log(event, payload);
}

emit("user.created", { id: 1 }); // OK

Common interview gotcha

What’s the difference between param?: string and param: string | undefined? The optional version lets us SKIP the argument at the call site; the union version forces us to pass undefined explicitly. Subtle but it shows up in API design.

function a(x?: string) {}
function b(x: string | undefined) {}

a();           // OK
b();           // Error — expected 1 argument
b(undefined);  // OK