Home > Mobile >  Inconsistency in TypeScript function overload
Inconsistency in TypeScript function overload

Time:09-29

Consider this example:

export function fn(arg: string): void;
export function fn(arg: number): void;
export function fn(arg: any) {
    console.log(arg);
}

So, fn can be called either with a string, or a number.

fn('hello!');
fn(42);

So far, so good. But then fn is executed in a different place:

function fn2(arg2: string | number) {
    fn(arg2);
}

In this case TypeScript complains:

No overload matches this call. Overload 1 of 2, '(arg: string): void', gave the following error.

Argument of type 'string | number' is not assignable to parameter of type 'string'.
  Type 'number' is not assignable to type 'string'.   Overload 2 of 2, '(arg: number): void', gave the following error.
Argument of type 'string | number' is not assignable to parameter of type 'number'.
  Type 'string' is not assignable to type 'number'.ts(2769) 

index.tsx(3, 17): The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.

Can someone help me understand what's going on here?

CodePudding user response:

Overloads aren't the same as Union Types. Overloads define 'separate' functions while unions allow you to put different types as arguments.

// fails
function fn2(arg2: string | number) {

    fn(arg2); // uses the union type
}

// works 
function fn3(arg2: string | number) {
    
    if(typeof arg2  === 'string') {
        return fn(arg2); // uses string
    }
    
    return fn(arg2); // uses number
}

This means fn2 searches for a function declaration that has an argument of type string|number while fn3 searches for either a function with type string or a function with type number as its first argument.

You should not use any if you exactly know, which type you want as a function parameter.

See the documentation for Union Types

CodePudding user response:

You can add another overload

export function fn(arg: string): void;
export function fn(arg: number): void;
export function fn(arg: any): void;
export function fn(arg: any) {
    console.log(arg);
}

fn('hello!');
fn(42);

function fn2(arg2: string | number) {
    fn(arg2);
}

Playground

  • Related