Demystifying Function Overloading in TypeScript
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
totrue
. - setting
asObservable
tofalse
.
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: