DEV Community

loading...

Predicates in Typescript

jackchapman profile image Jack ・2 min read

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() {};
}
Enter fullscreen mode Exit fullscreen mode

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();
       ^^^^
Enter fullscreen mode Exit fullscreen mode
Property 'swim' does not exist on type 'Fish | Bird'.
Property 'swim' does not exist on type 'Bird'.
Enter fullscreen mode Exit fullscreen mode

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';
}
Enter fullscreen mode Exit fullscreen mode

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();
         ^^^
}
Enter fullscreen mode Exit fullscreen mode
Property 'swim' does not exist on type 'Bird'.
Property 'fly' does not exist on type 'Fish'.
Enter fullscreen mode Exit fullscreen mode

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';
}
Enter fullscreen mode Exit fullscreen mode

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

Hope that helps!

Discussion (0)

pic
Editor guide