TypeScript by Example

Function Types and Overloads

Typing callbacks, higher-order functions, stored function references, and overload signatures.

Functions are values. TypeScript can name their shape and express multiple call signatures when one implementation supports them.

A function type expression describes the shape of a callback or stored function reference.

type Predicate<T> = (value: T) => boolean;
type Transform<A, B> = (input: A) => B;
 
function filter<T>(arr: T[], pred: Predicate<T>): T[] {
  return arr.filter(pred);
}
 
function map<A, B>(arr: A[], fn: Transform<A, B>): B[] {
  return arr.map(fn);
}

Overloads let callers see precise signatures while the implementation handles the union internally.

function parse(input: string): number;
function parse(input: number): string;
 
function parse(input: string | number): number | string {
  if (typeof input === "string") return parseInt(input, 10);
  return input.toString();
}
 
const n = parse("42"); // number
const s = parse(42); // string

In production

Use overloads when one function has distinct public call shapes. Avoid widening the public signature to any just to make the implementation easy; that disables checking for every caller.

Enjoyed this? Get more software craft delivered to your inbox.