Chris Bier
Chris Bier

Reputation: 14455

Why can't I call an overloaded function in this manner?

Take this example of function overloading:

function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any {
      /* ... */
}

In the Handbook it says:

Note that the function pickCard(x): any piece is not part of the overload list, so it only has two overloads: one that takes an object and one that takes a number. Calling pickCard with any other parameter types would cause an error.

Therefore I cannot call pickCard("test");. It throws an error.

If pickCard(x) is not a valid function signature, then why do we have to write it? What is the benefit of having it around? Is there a use case that I am not thinking of?

Check out the playground example

Upvotes: 1

Views: 155

Answers (1)

Nitzan Tomer
Nitzan Tomer

Reputation: 164367

The first two are just signatures, to specify what are the different options are for calling the function.

The third is the actual function definition, and it just receives one argument and returns any.
In it you implement the actual logic, check what are the types that the function received and return the appropriate value according to the passed params.

For example:

function a(str: string): string;
function a(num: number): number;
function a(value: any): any {
    if (typeof value === "string") {
        return (parseInt(value) * 2).toString();
    } else {
        return value * 2;
    }
}

a("3"); // should be "6"
a(3); // should be 6
a(true); // error

You need to have the third because otherwise you'll need to use one of the other signatures as the actual function definition.
If you choose the first then the parameter is a string not a number, if you go with the 2nd one then the parameter is a number not a string.
That's why the 3rd one is there, it figures out what the actual params that were passed in and based on that carries it's logic.

You can also have different number of properties:

function b(a: number): number;
function b(a: number, b: number): number;
function b(...args: number[]): any {
    if (args.length == 1) {
        ...
    } else {
        ...
    }
}

Which is usually the scenario in which you'll use different signatures, cuz for same number of params with different types you can simply:

function a(value: string | number): any {
    if (typeof value === "string") {
        return (parseInt(value) * 2).toString();
    } else {
        return value * 2;
    }
}

Upvotes: 2

Related Questions