TypeScript errors for humans: "no overload matches this call"
I must have read the error in the title a thousand times until I finally learned its meaning this week. Hereâs a tip for everyone and myself: read the f*cking error message; break down the sentence into keywords and use that Google-flex to find out what it means.
Rather than search what âoverloadâ meant, I would appease the compiler by reading the types provided and trying to figure out how to fit the params or the return value to the valid type (or adding // @ts-ignore
or any
). This worked (since I was actually trying to get closer to solving the error), but the error message still scared me because I think âwtf does that error message even meanâ. But now, thanks to these TypeScript exercises, Iâve finally learned what âoverloadâ means.
What is an overload?
[or, here is where Iâm lazy and mostly copy-paste from reputable sources (with references of course - I am not a monster).
You encounter overloads when you write any function in TS. From trusty Wikipedia, function overloading is:
the ability to create multiple functions of the same name with different implementations
TypeScript leans more on the âsame nameâ idea and applies this idea to a sinlge function. A single function can have different implementations; these different implementations are usually based in the kinds of inputs you give to the function.
From the TS documentation, we can see the function pickCard
differs its return value depending on whether typeof x
is an object (reading ahead that .length
implies x
to be an array) or a number. Giving pickCard
an array will output a number, while a number will output a card object ({suit: string, card: number}
).
let suits = ["hearts", "spades", "clubs", "diamonds"];
function pickCard(x: any): 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") {
let pickedCard = Math.floor(Math.random() * x.length);
return pickedCard;
}
// Otherwise just let them pick the card
else if (typeof x == "number") {
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13 };
}
}
Knowing that an array argument will only ever return a number, while a number argument will only return a card object, how do we type this? We give the function a list of overloads:
Slightly modified from the TS docs:
function pickCard(x: { suit: string; card: number }[]): number;
function pickCard(x: number): { suit: string; card: number } {
// 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") {
let pickedCard = Math.floor(Math.random() * x.length);
return pickedCard;
}
// Otherwise just let them pick the card
else if (typeof x == "number") {
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13 };
}
}
Now, when you use pickCard()
function with an array of card object, TS will automatically tell you that the return value will be a number. It wonât say âoh it could be a number or a card objectâ; it will follow the overloads given to the function and find the return value suited to it.
So when I next see âno overload matches this callâ, it wonât necessarily mean that I need to give it another overload, as illustrated above. It will more likely mean that I need to double check types and change them as needed. However, now know what an overload is, I feel less scared of the error message.
Resources
- TypeScript exercises. Highly recommend these to get to know TS better
- TS documentation on overloads. What I mostly copy-pasted from