How to condition a function's output type based on its input type in Typescript
Nick Scialli
September 10, 2022
Typescript is most helpful when we can use it to assert things that we know are true about our code. Sometimes, however, it can be difficult to figure out the right incantation to make that happen.
In this post, we’ll learn how to condition a function’s output type based on its input type.
An example
Let’s create a contrived example. We’ll have a function flipType
that takes a number
or a string
as an argument. If the argument is a number
, the return type should be a string
, and if the argument is a string
, the return type should be a number.
If we were to try to naively implement this, it might look something like this:
function flipType(arg: number | string): number | string {
if (typeof arg === 'string') {
return 5;
}
return 'some string';
}
This will compile just fine, but it doesn’t work how we want it to—it doesn’t narrow the return type of our function when we call it. For example:
const result1 = flipType('hello');
const result2 = flipType(5);
result1
should be a number
type and result2
should be a string
type, but they aren’t being narrowed and are bout number | string
typed.
Overloads to the rescue
We’re saved here by function overloads. Function overloads let you define different scenarios for the function just before the function’s actual declaration.
Let’s see function overloads in action with our example:
function flipType(arg: string): number;
function flipType(arg: number): string;
function flipType(arg: number | string) {
if (typeof arg === 'string') {
return 5;
}
return 'some string';
}
We have defined two different scenarios by using the function overload syntaxt: if our arg
is a string
, the return type should be number
, and vice versa.
We can now use this function and gain the advantage of knowing the exact type of the returned variable!
Nick Scialli is a senior UI engineer at Microsoft.