Function Overloads

Defining multiple signatures for a single function.

TypeScript4 min readConcept 19 of 54

Multiple Personalities

Sometimes a function can be called in entirely different ways. For example, a getDate function might accept a timestamp (number) OR it might accept a year, month, and day (three numbers).

Function Overloads allow you to define multiple strict type signatures for a single function, ensuring the caller gets the correct return type based on exactly which arguments they passed.

When Unions aren't enough

Why not just use a union type like function get(arg: string | string[])? Because if you return a different type based on the argument (e.g., returning a single item vs an array of items), the return type becomes a messy union (Item | Item[]).

Overloads allow you to say definitively: 'If you pass a string, I return an Item. If you pass an array, I return an Item array.'.

The Signature Stack

You write the overload signatures first, followed by one single implementation signature that handles all the logic.

typescript // 1. Signature for single ID function getUser(id: number): User; // 2. Signature for multiple IDs function getUser(ids: number[]): User[]; // 3. The Implementation (must cover all cases) function getUser(idOrIds: number | number[]): User | User[] { if (Array.isArray(idOrIds)) { return idOrIds.map(fetchUser); } return fetchUser(idOrIds); }

Try it

Select which overload signature to invoke. Watch how the single implementation block handles the different argument types to return different outputs.

// 1. Overload: Single ID
function get(id: number): User;
// 2. Overload: Multiple IDs
function get(ids: number[]): User[];

// 3. Implementation (Invisible to caller)
function get(arg: any) {
if (Array.isArray(arg)) {
return arg.map(fetch);
}
return fetch(arg);
}

const res = get(42);
Compiler Output
res: User

Matched Overload #1. The compiler perfectly infers a single User return type based on the single number argument.

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1Can a caller directly invoke the final implementation signature of an overloaded function?

Remember this

  • Overloads are multiple type signatures stacked above a single implementation.
  • Use them when the return type depends on the argument types.
  • The implementation signature must broadly cover all overload cases.
  • The implementation signature itself is invisible to the caller.

Done with this concept?

Mark it complete to track your progress. No login needed.