Search code examples
typescripttypescript-typings

Overload functions with paramters of `T` and `T | undefined` in TypeScript


I defined a simple function with overload siganatures:

function toUpper(value: string | undefined): string | undefined;
function toUpper(value: string): string ;
function toUpper(value: string | undefined): string | undefined {
    return value?.toString();
}

And hope when passing value is string that the return type is string, and when passing value is string | undefinedthat the return type isstring | undefined`

But the simple call reports compilation error:

const x: string = toUpper('abc');
TS2322: Type 'string | undefined' is not assignable to type 'string'.   Type 'undefined' is not assignable to type 'string'.

Please help how to define the function correctly, thanks!


Solution

  • Function overload signatures need to be sorted from most specific to least specific. Here we're working with Union Types hence the signature with fewer union members (string) must be written before the other one (string | undefined).

    ❔ Why: TypeScript chooses the first matching overload when resolving function calls. When an earlier overload is “more general” than a later one, the later one is effectively hidden and cannot be called.

    See function overloads Do's and Don'ts

    So your overload signature that takes a string was actually being ignored and string | undefined was returned instead which is not assignable to the explicit type annotation of const x: string = .... -> compiler error.

    function toUpper(value: string): string;
    function toUpper(value: string | undefined): string | undefined {
        return value?.toString();
    }
    
    const x: string = toUpper('abc');
    

    TypeScript Playground