Feb 4th, 2022 - written by Kimserey with .
Type predicate in Typescript allows us to narrow down the type of a variable using a predicate. Today we’ll look at how to use type predicates, and show examples where they are useful.
A type predicate takes the form of {variable} is {type}
and is used on return type of functions.
1
2
3
4
5
6
7
8
9
10
11
12
13
interface Person {
name: string;
}
interface House {
address: string;
}
const values: (Person | House | string)[] = [
{ name: "Kim" },
{ address: "123 street" },
"hello world",
];
In this example, we have two interfaces Person
and House
where the variable values
is an array of a union between both and string
.
Right after the declaration of values
, the type will be (Person | House | string)[]
.
If we want to narrow down the type to either Person
or House
or string
, we can create a function returning a type predicate.
1
2
3
function isPerson(value: Person | House): value is Person {
return (value as Person).name !== undefined;
}
The type predicate value is Person
informs the compiler that if the predicate (value as Person).name !== undefined
returns true
, value
will be of type Person
, else it will not be of type Person
- meaning it will be of type House | string
.
This construct is very useful as it allows the compiler to narrow down the type so that within the control statement, we are dealing with only the specific type.
Using the same isPerson
predicate, we can define another predicate for isHouse
:
1
2
3
function isHouse(value: Person | House | string): value is House {
return (value as House).address !== undefined;
}
Then we can see that when using the predicates which return type predicates, we are able to indicate to the compiler the correct types we are dealing with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for (const v of values) {
// v is `Person | House | string`
if (isPerson(v)) {
// v is `Person`
} else {
// v is `House | string`
if (isHouse(v)) {
// v is `House`
} else {
// v is `string`
}
}
// v is `Person | House | string`
}
Type predicates can also be used in arrow functions to narrow down the type in array functions.
1
2
3
4
5
values
.filter((v): v is Person => (v as Person).name !== undefined)
.forEach((v) => {
// v is `Person`
});
And that concludes today’s post!
Today we looked at how we could use type predicate to narrow down types. We started by looking at how to define type predicate, we looked at how the type narrowing was finding the right types within the control flows. We then completed the post by looking at an example of type predicate used in arrow function. I hope you liked this post and I’ll see you on the next one!