Typing Functions with Overloading, Values, and Arrow Functions


Overloading allows us to to define multiple function signatures for one function. We can think of it as pattern matching based on the input types that a function is called with.

Let's say we have a function prefix() that takes two arguments: a prefix and a string (or array of strings) that should have the prefix. If we are given a string as the second parameter, our function should return the result of concatenating the prefix to that string. If we are given an array of strings as the second parameter, our function should return an array of strings, where each string is the result of concatenating the prefix to that string.

As a first step towards typing prefix(), we might try to use union types to achieve what we need:

At first look this function appears to type our function correctly. The problem arises when we try to use the return value as either a string or an array:

Union return types are not dynamic, so even though we know that book is type string and books is type string[], the TypeScript compiler treats the return value statically as a union of string and string[]. Any operation that we run on the return value of prefix() has to work for both string and string[], which is problematic when we want to use one or the other.

Instead of using union types, we define overloads for our prefix() function to specify dynamic return types based on the input types passed to the function:

Function overloads consist of two parts:

  1. One or more function signatures, which consist of parameter types and a return type. We can read these as: "when given these input type(s), return this output." The argument list can vary in length and type, giving us the flexibility to choose different return types for different argument lengths as well as different argument types.

  2. One function definition. This is the function that has a body. This function's signature must be a superset of all the overloads, meaning that we have to take into account all input types and all return types when annotating our function definiton.

In the example below, we define a function getEmployeeInfo() whose return type depends on the input object type:


This page is a preview of Beginners Guide to TypeScript

Start a new discussion. All notification go to the author.