← Back to TypeScript Course | Chapter 3: Variables and Functions | Lesson 10 of 10

Function Overloading

Function overloading allows TypeScript to describe multiple valid ways to call the same function. Each overload provides a different call signature while a single implementation handles the actual logic.

Basic Function Overloads

Function overloading starts by writing multiple overload signatures, each describing one valid combination of parameter types, directly above a single shared implementation signature. Callers only ever see and choose from the overload signatures, never the implementation's own signature.

Example: Basic Function Overloads

typescript
function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
  return `Value: ${value}`;
}
console.log(format("hi"), format(5));

Overloading with Different Parameters

Overload signatures can describe functions that accept entirely different numbers or combinations of parameters, such as one overload taking a single string and another taking a string plus a number. TypeScript picks the matching overload based on how the function is actually called.

Example: Overloading with Different Parameters

typescript
function combine(a: string): string;
function combine(a: string, b: number): string;
function combine(a: string, b?: number): string {
  return b === undefined ? a : `${a}-${b}`;
}
console.log(combine("id"), combine("id", 42));

Overload Implementation

The implementation signature underneath all the overloads must be broad enough in its own types to satisfy every overload's promises, even though callers never call that signature directly. This is what lets a single function body correctly handle every declared overload case.

Example: Overload Implementation

typescript
function toArray(value: string): string[];
function toArray(value: number): number[];
function toArray(value: string | number): (string | number)[] {
  return [value];
}
console.log(toArray("x"), toArray(1));

Overloads and Return Types

Different overloads are free to specify different return types depending on which input pattern was matched, letting the compiler give callers a precisely typed result instead of one overly broad union type. This is one of overloading's biggest practical benefits.

Example: Overloads and Return Types

typescript
function parseValue(value: string): number;
function parseValue(value: number): string;
function parseValue(value: string | number): number | string {
  return typeof value === "string" ? Number(value) : String(value);
}
console.log(parseValue("42"), parseValue(42));

When to Use Function Overloading

Reach for function overloading when a single function naturally supports several distinct, well-defined input patterns and you want TypeScript to give callers precise, pattern-specific type checking. For simpler cases, a single signature using union types or optional parameters is usually easier to maintain.

Example: When to Use Function Overloading

typescript
function makeDate(timestamp: number): Date;
function makeDate(year: number, month: number, day: number): Date;
function makeDate(a: number, b?: number, c?: number): Date {
  return b === undefined ? new Date(a) : new Date(a, b, c);
}
console.log(makeDate(2024, 0, 1));

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.