What is a predicate?
It's pretty common to use helper functions throughout your code to determine whether something is or isn't a thing.
The definition of the word predicate is, simply put:
to say that something is true
So, you can call your isFoo
and isBar
functions predicates.
How about an example?
Say for example we can magically create an animal but, for some reason, that animal can only be a Bird
or Fish
...
Now these two animals are pretty different, so we'd need to define them differently
class Bird {
fly() {};
}
class Fish {
swim() {};
}
As you can see, a Fish
can swim
and a Bird
can fly
, but not the other way round.
Let's get one at random and see if we can figure out how to tell it to fly
or swim
.
const animal: Bird | Fish = getAnimal();
animal.swim();
^^^^
Property 'swim' does not exist on type 'Fish | Bird'.
Property 'swim' does not exist on type 'Bird'.
Oh dear!
We need to make sure we only run animal.swim()
when the animal
is a Fish
Let's make a predicate!
function isFish(maybeFish: any) {
return typeof maybeFish.swim === 'function';
}
By default, typescript can tell that the return type of isFish
is boolean
. But that's not as helpful as we might think...
if (isFish(animal)) {
animal.swim();
^^^^
} else {
animal.fly();
^^^
}
Property 'swim' does not exist on type 'Bird'.
Property 'fly' does not exist on type 'Fish'.
Typescript cannot tell that you're explicitly testing whether animal
is of type Fish
or not in isFish
. We need to explain that we return true
if maybeFish
is a Fish
.
Turns out that's a very simple fix!
function isFish(maybeFish: any): maybeFish is Fish {
return typeof maybeFish.swim === 'function';
}
We can use that magic maybeFish is Fish
there to tell typescript This function will return true if maybeFish
is of type Fish
and false if it is not!
This is called a type predicate
Top comments (1)
Thank you for this simple post. I had never wrapped my mind around predicates in Typescript, but this made it crystal clear. So simple! Thanks!