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:

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

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 Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more