Function overloading in TS is the ability to create multiple declarations for a function. We will show how to use it on a function that has several return types, so the compiler can determine the return type based on the input type.

A Basic Example

Let’s say I have a function that creates a new color shade from a given color:

As we can see, the function supports both strings and RGB objects as inputs, and returns the new color in the same input type it was given.

The Problem

Since this function can return either a string or an RGB object, if we try to do the following:

We’ll get a compilation error.

This behaviour makes sense, as the compiler doesn’t know which return type to expect.

The Solution

All we have to do is to add some function declarations/overloads!

This way we can help the compiler determine what would be the output type, based on the input type.

We added 2 overloads to the colorShade() function:

The first overload tells the compiler that when the color argument is a string it should infer the return type is a string . The second overload does the same but for an RGB object.

That’s it! now the compiler knows how to match the return types.

Advanced Examples

The previous example was very basic, let’s see some more complex overloads taken from Akita:

#1 Default values

Let’s take a look at this function, which has a parameter with default value:

The above function returns a boolean or an observable . The type of the result is determined by the asObservable param.

We can call the function in three different ways:

Without passing the second parameter. setting asObservable to true . setting asObservable to false .

So our overloads should cover of all these cases and look like this:

Note that when using overloads, you should list the declarations from the most specific case to the most general one.

#2 Complicated Options Object

Let’s take a look at selectAll function from Akita’s entity query:

The selectAll() function accepts an options object and returns an observable of either an Array or HashMap .

Let’s take a look at the function signature:

We can see that the asObject property from the options object is the one which determines the return type.

# First overload

We are expecting an options object with asObject set to true , therefore the return type is Observable<HashMap<E>> .

When looking at the expected parameters we can see something interesting: We’re allowed to use the sortBy option only if the asObject key is set to false .

# Second overload

We are expecting an options object with asObject set to false , therefore the return type is Observable<E[]> .

We can also see that sortBy can be passed in this case, since the return value is an Array which is sortable.

# Third overload

We can call the selectAll() function without passing any params.

Recap

Overload declarations help the complier determine the function’s return type by the input type. When using overloads you should list the declarations from the most specific case to the most general one. We saw an advanced use case where we passed an object, and based on one of its keys we determined the type of the return value.

Thank you for reading!

If you liked the article hit the 👏🏻 button and share it 🎉

Last but Not Least, Have you Heard of Akita? 👂

Akita is a state management pattern that we’ve developed here in Datorama. It’s been successfully used in a big data production environment for over seven months, and we’re continually adding features to it.

Akita encourages simplicity. It saves you the hassle of creating boilerplate code and offers powerful tools with a moderate learning curve, suitable for both experienced and inexperienced developers alike.

I highly recommend checking it out.

New Angular Meetup in Tel-Aviv

We’ll be hosting a meetup entitled “Kickass Angular” where we’ll be showcasing the cutting edge technologies we use/have come up with.

Signup and reserve a seat! 🍕

Here is more great content from my team: