typescript - is return-type signature in function overloading useless?

Function overloading in Typescript has a unexpected behavior.

Taking a look at the function overloading example, the return-value signature is part of the function overloading. However, the return type seems to get ignored completely. It is not necessary for Typescript to 'pick' the correct function argument signature and, what bothers me most, it is not used for checking the correct return value.

If the return value of card is changed from a number to a string, Typescript doesn't give any warning.

function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any {
  // Check to see if we're working with an object/array
  // if so, they gave us the deck and we'll pick the card
  if (typeof x == "object") {
    var pickedCard = Math.floor(Math.random() * x.length);
    return pickedCard;
  }
  // Otherwise just let them pick the card
  else if (typeof x == "number") {
    var pickedSuit = Math.floor(x / 13);
    return { suit: suits[pickedSuit], card: x % 13 }; // <-- change to card: '13'
  }
}

My question is: am I interpreting the overload mechanism correctly, so is supplying a return-value signature not necessary or it this a bug?

1 Answer

  1. Leonard- Reply

    2019-11-13

    When I call your function, I get the following types returned:

    // a is number
    var a = pickCard([{ suit: 'hearts', card: 1 }]);
    
    // b is {suit: string; card: number; }
    var b = pickCard(1);
    

    This saves me from having to specify it manually:

    // a is number
    var a: number = pickCard([{ suit: 'hearts', card: 1 }]);
    
    // b is {suit: string; card: number; }
    var b: {suit: string; card: number; } = pickCard(1);
    

    If you were to get them "the wrong way around", you would indeed get errors about the types:

    // a is number
    var a: {suit: string; card: number; } = pickCard([{ suit: 'hearts', card: 1 }]);
    
    // b is {suit: string; card: number; }
    var b: number = pickCard(1);
    

    So the overload is indeed being picked based on the argument you pass - and the return type is adjusted based on the selected overload.

    View this example on the TypeScript Playground.

Leave a Reply

Your email address will not be published. Required fields are marked *

You can use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>