DEV Community

Krzysztof Żuraw
Krzysztof Żuraw

Posted on

10 2

TypeScript function overloads

NOTE: This is cross-post from my newsletter. I publish each email after it’s sent. Subscribe to get more content like this earlier right in your inbox! 📧.

Hello 👋🏻
Today I want to write a little bit about functions overloads in TypeScript. I will explain what is function overload and how to do it. In the next section, I will cover why you may want to overload your functions and what is a proper way of doing it.

During this article, I assume that you have at least basic knowledge of TypeScript.

Table of contents

What

Function overloads is a way of telling TypeScript that this function may take different arguments.
Let’s jump into an example:

interface Data {
    postalCodes: string[];
    country: string;
}

const data: Data = {
    postalCodes: ['123', '422'],
    country: 'PL'
}
Enter fullscreen mode Exit fullscreen mode

This is a bit contrived example but it illustrates the point. I have an object data which fulfills interface Data. This object has two keys postalCodes & country which are string[] and string type respectively.

Below I have getDataByKey which is a helper to get either postalCodes or country.

function getDataByKey(data: Data, key: 'postalCodes' | 'country') {
    return data[key];
}

const postalCodesRetrieved: string[] = getDataByKey(data, 'postalCodes')
Enter fullscreen mode Exit fullscreen mode

Everything looks nice so far but at the last line I want my postalCodesRetrieved to be array of string. Yet compiler will return and error:

Type 'string | string[]' is not assignable to type 'string[]'.
  Type 'string' is not assignable to type 'string[]'.
Enter fullscreen mode Exit fullscreen mode

You can find a playground with this problem under this link.

Why & How

How to fix it? You can use function overloading:

function getDataByKey(data: Data, key: 'postalCodes'): string[]
function getDataByKey(data: Data, key: 'country') : string
function getDataByKey(data: Data, key: 'postalCodes' | 'country') {
    return data[key];
}
Enter fullscreen mode Exit fullscreen mode

I write two overloads for getDataByKey: one is taking country as a key and returns string. Another one takes postalCodes and returns string[]. Thanks to that I can use getDataByKey with both keys:

const postalCodesRetrieved: string[] = getDataByKey(data, 'postalCodes')
const countryCodesRetrieved: string = getDataByKey(data, 'country')
Enter fullscreen mode Exit fullscreen mode

You can even see that this function is overloaded by hovering:
Imgur

Link to TypeScript playground with code from above.

Function overloads in an arrow function

interface GetData {
    (data: Data, key: 'postalCodes'): string[];
    (data: Data, key: 'country'): string
}

const getData: GetData = (data, key) => {
    return data[key];
}

const postalCodesRetrieved: string[] = getData(data, 'postalCodes');
const counryRetrieved: string = getData(data, 'country');
Enter fullscreen mode Exit fullscreen mode

This is working by GetData interface where overload is happening. Thanks to that I don’t need to type data & key arguments anymore. Playground link

Function overloads in class methods

class DataGetter {
    getData(data: Data, key: 'country'): string;
    getData(data: Data, key: 'postalCodes'): string[];
    getData(data: Data, key: 'postalCodes' | 'country') {
        return data[key];
    };
}

const dataGetter = new DataGetter();

const postalCodesRetrieved: string[] = dataGetter.getData(data, 'postalCodes')
const counryRetrieved: string = dataGetter.getData(data, 'country')
Enter fullscreen mode Exit fullscreen mode

It looks almost the same as for normal function but here getData method is overloaded. Playground link

Summary & TL;DR

In this post, I presented a way of telling TypeScript that the same function can be called with different parameters or returns different results. This is a function overloading. You can overload class methods too. In the simplest example, you need to write a declaration of override function at the top of a function definition.

Do you use it? If so where? Drop a comment below.

You can find all playgrounds links here:

Image of Stellar post

How a Hackathon Project became a Web3 Startup 🚀

Ever wondered what it takes to build a web3 startup from scratch? In the Stellar Dev Diaries series, we follow the journey of a team of developers building on the Stellar Network as they go from hackathon win to getting funded and launching on mainnet.

Watch the video

Top comments (3)

Collapse
 
b2whats profile image
Akimov Vladimir

heh, not work without args type bit.ly/arrowOverload

Collapse
 
captweiss profile image
Capt. Weiss (Kolade O. Adetoyinbo) • Edited

yeah that's true, but you can get it all working by simply casting the return value type to any
like this

Collapse
 
szulcus profile image
Jakub Schulz • Edited

Sad that it doesn't support union types 😥. Is using @ts-expect-error as a workaround in your opinion a good solution?

Image of Stellar post

🚀 Stellar Dev Diaries Series: Episode 1 is LIVE!

Ever wondered what it takes to build a web3 startup from scratch? In the Stellar Dev Diaries series, we follow the journey of a team of developers building on the Stellar Network as they go from hackathon win to getting funded and launching on mainnet.

Read more

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay