The Utils Folder 10 exercises

Implement Function Overloads

Function overloads allow you to define multiple ways a function can be called. They look like several extra function keywords above the function, followed by an implementation signature.

For reference, here's how the sum function started:

function sum(valuesOrA: { a: number; b: number }

Loading solution


00:00 Function overloads in TypeScript lets you basically declare different ways, different patterns that a function can be called. If you look at some function overloads, you're going to see several sort of like types above the function, which are basically just sort of extra function keywords. And then finally, an implementation signature for the function. So let's take a look at this.

00:20 What we can do is we can actually add in, let's actually look at the, just the A number, B number set up first. We can say function sum, and this is going to be values, is going to be A number, B number. Let's copy that over. And then we have to also declare a return type as well. So currently it's saying sum,

00:38 which lacks return type annotation implicitly hasn't any return type. So we have to give it a return type here. So now sum, you can see that it's starting to work already. We're getting a nice little bit of like erroring down here, where if we try to pass in two numbers, it's going to yell at us.

00:55 And if we call sum now, so let's say we have sum here, then it's actually only going to show us this first signature there. So if we think about this last signature, this is called the implementation signature. And this one is private. So only the ones that are above the implementation signature

01:14 actually get exposed to outside users here. So the only way we can call this right now, we cannot pass one and two here because it's going to yell at us because arguments of type number is not assignable to parameter of type A number, B number. So this is what's happening.

01:29 Only this version of the function is getting exposed to the outside world. So we need to add another version where we can say values is going to be A number and B number. You can see here on the first one, we have an object which is being exposed, a single object called values. And this one, we have two different parameters

01:48 that are being exposed, A number and B number. And now it works great. We can either call this, you can actually cycle through the versions of the overload that are available. So we have A number, B number. Let's take a look at the second one. So now we can pass in A or one and two. And if we try to pass in an invalid combination,

02:07 then it's actually going to yell at us here. So A number, B number is not assignable to parameter of type number. Because we've passed in two arguments, we've hit that second signature. And now basically it's yelling at us because we're trying to pass an object where it's expecting a number. And this one here, we're passing in a number as the first argument.

02:26 And it's yelling at us because, you know, it's basically expecting A number, B number in that slot because we've passed two few arguments. This is great. It's giving us a nice sort of understanding from the user's point of view of how this function can be called. Now, if we look inside our implementation signature,

02:43 you might notice that B, like number here, number or undefined, we cannot actually turn this into something that's always passed. Because the implementation signature has to be compatible with the other overload. So this overload is not compatible with its implementation signature.

03:01 So this one assumes that however you call this function, you're always going to get a second parameter. So this is a bit of a downside because whatever we declare in these first overloads here, this has to be kind of mashed together in the implementation signature, meaning that you do get a little bit of confusing code.

03:19 But the point here is that function overloads let you, if you have a sort of what's called a polymorphic signature, many different patterns, ways that you can pass in things into your function overload, then this lets you do it. And this gives you a way of doing it. There are not many arguments for doing this in application code,

03:38 but it will sometimes come up. And it's especially true when you have different numbers of parameters because we've looked at union types before. And you might think, why can't I just use a union type here? Well, the reason is because it's split over multiple parameters.

03:53 So this first one, if it was only literally just values or A up here, then there's no need for these function signatures here, right? So these function overloads, you would literally just have values or A. But because we have B here, it gets a little bit more complicated. And it means that we need to add in some overloads

04:11 to declare the different parameter types that you can pass in. So function overloads, occasionally useful, certainly one of the most advanced things we've looked at so far. And they give you a nice tool for expressing different ways of understanding functions in TypeScript.