Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Function overloading in TypeScript is a structural mechanism that allows a single function to possess multiple distinct call signatures. It enables the TypeScript compiler to perform precise type resolution and enforce strict type checking based on the specific combination of arguments passed at invocation, mapping them to a corresponding return type. In standard execution contexts, a TypeScript overloaded function consists of two distinct parts:
  1. Overload Signatures (Declarations): One or more function declarations without a body. These define the public API and dictate exactly how the function can be invoked.
  2. Implementation Signature: A single function definition with a body. This signature must be structurally compatible with all preceding overload signatures, but it is entirely hidden from the caller.
// 1. Overload Signatures
function parseData(data: string): string[];
function parseData(data: number, radix: number): string[];
function parseData(data: boolean): null;

// 2. Implementation Signature
function parseData(data: string | number | boolean, radix?: number): string[] | null {
    if (typeof data === "string") {
        return data.split("");
    } else if (typeof data === "number") {
        return data.toString(radix || 10).split("");
    }
    return null;
}
However, in ambient declarations (such as within .d.ts files or when using the declare keyword), overloaded functions consist exclusively of overload signatures and omit the implementation signature entirely.
// Ambient Overloads (No implementation signature)
declare function fetchResource(url: string): Promise<string>;
declare function fetchResource(id: number): Promise<Record<string, unknown>>;

Core Mechanics and Rules

Implementation Compatibility The implementation signature must use type unions, optional parameters, or top types (any, unknown) to satisfy every preceding overload signature. If an overload signature specifies a return type of string and another specifies number, the implementation signature must return string | number. Caller Visibility The implementation signature is invisible to the type system during invocation. The external API is strictly defined by the overload signatures. In the example above, calling parseData with a union type like string | boolean will result in a compiler error, even though the implementation signature technically accepts it, because no single overload signature accepts that union. Resolution Order The TypeScript compiler evaluates overload signatures sequentially from top to bottom. The first signature whose parameter types satisfy the provided arguments is selected. Consequently, more specific signatures (e.g., literal types or exact object shapes) must be declared before more generic signatures (e.g., any or broad unions) to prevent the compiler from prematurely resolving to a broader type.

Class Method Overloading

Class methods are overloaded directly within the class body using the exact same pattern as standard function declarations: multiple method signatures followed by a single implementation signature.
class DataProcessor {
    // Overload Signatures
    process(item: string): string;
    process(item: number, multiplier: number): number;
    
    // Implementation Signature
    process(item: string | number, multiplier?: number): string | number {
        if (typeof item === "string") return item.toUpperCase();
        return item * (multiplier ?? 1);
    }
}

Overloading Arrow Functions via Types and Interfaces

Because standard arrow functions cannot be overloaded using the function keyword syntax, overloading for arrow functions is achieved by defining multiple call signatures within an interface or an object type alias.
type Formatter = {
    (value: string): string;
    (value: number, decimals: number): string;
};

// The implementation uses a broad signature to satisfy the Formatter type
const format: Formatter = (value: any, decimals?: any): string => {
    if (typeof value === "number") {
        return value.toFixed(decimals);
    }
    return value.trim();
};
Master TypeScript with Deep Grasping Methodology!Learn More