{
    "slug": "typescript_overloads",
    "term": "TypeScript Function Overloads",
    "category": "typescript",
    "difficulty": "intermediate",
    "short": "TypeScript function overloads allow a single function to accept different argument shapes and return different types based on which overload signature matches — providing precise type checking that union types alone cannot express.",
    "long": "A function overload consists of two or more overload signatures (no body) followed by one implementation signature (with body). TypeScript uses the overload signatures for type checking and IDE autocomplete — the implementation signature is hidden from callers. Overloads are useful when the return type depends on the input type (e.g. createElement('div') returns HTMLDivElement, createElement('canvas') returns HTMLCanvasElement), or when a function accepts fundamentally different argument shapes. The implementation must be compatible with all overload signatures. Method overloads work the same way in classes.",
    "aliases": [
        "function overloads",
        "TypeScript overloads",
        "overload signatures"
    ],
    "tags": [
        "typescript",
        "type-system",
        "functions",
        "inference"
    ],
    "misconception": "The implementation signature is visible to callers. It is not — callers only see the overload signatures. The implementation signature is often broader (using union types) and would be confusing or permissive if exposed.",
    "why_it_matters": "Without overloads, functions that return different types based on input force callers to narrow the type themselves or use unsafe casts. Overloads encode the relationship between input and output types precisely — 'when you pass a string you get a string back, when you pass a number you get a number back' — making the API self-documenting and type-safe.",
    "common_mistakes": [
        "Putting the implementation signature before the overload signatures — TypeScript requires all overload signatures first, then the implementation.",
        "Making the implementation signature narrower than the overloads — the implementation must accept the union of all overload parameters.",
        "Using overloads when conditional types or generics would be cleaner — overloads are best for a small number of distinct cases; for many cases use generics with conditional return types.",
        "Exposing too many overloads — each overload adds cognitive load; prefer 2–4 well-chosen overloads over exhaustive enumeration."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "typescript_types",
        "typescript_generics",
        "typescript_discriminated_unions",
        "typescript_conditional_types"
    ],
    "prerequisites": [],
    "refs": [
        "https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads"
    ],
    "bad_code": "// ❌ Union return type — caller must narrow every time\nfunction parseInput(input: string | number): string | number {\n    if (typeof input === 'string') return input.toUpperCase();\n    return input * 2;\n}\n\nconst result = parseInput('hello');\n// result: string | number — TypeScript doesn't know it's string\nresult.toUpperCase(); // Error: Property 'toUpperCase' does not exist on type 'string | number'",
    "good_code": "// ✅ Overloads — return type matches input type\nfunction parseInput(input: string): string;\nfunction parseInput(input: number): number;\nfunction parseInput(input: string | number): string | number {\n    if (typeof input === 'string') return input.toUpperCase();\n    return input * 2;\n}\n\nconst s = parseInput('hello'); // TypeScript knows: string\ns.toUpperCase();                // ✓ No error\n\nconst n = parseInput(42);       // TypeScript knows: number\nn.toFixed(2);                   // ✓ No error\n\n// Class method overload\nclass EventEmitter {\n    on(event: 'data',  listener: (data: Buffer) => void): this;\n    on(event: 'error', listener: (err: Error)  => void): this;\n    on(event: string,  listener: Function):                this {\n        // implementation\n        return this;\n    }\n}",
    "quick_fix": "When a function returns different types based on a flag or argument type, express it with overloads rather than a union return type — the overloads carry the correlation between input and output that a plain union loses.",
    "effort": "medium",
    "created": "2026-03-23",
    "updated": "2026-03-23",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/typescript_overloads",
        "html_url": "https://codeclaritylab.com/glossary/typescript_overloads",
        "json_url": "https://codeclaritylab.com/glossary/typescript_overloads.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[TypeScript Function Overloads](https://codeclaritylab.com/glossary/typescript_overloads) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/typescript_overloads"
            }
        }
    }
}