How to use Type guards in Typescript
A tutorial on how to correctly differentiate between types in Typescript
Union types can be quite useful when multiple types have overlapping properties; for example, Animals all have names, but some animals bark, some meow, some moo, etc...
But how can we find the difference between the types?
At some point, it becomes important when we want an animal to raise its sound to know if it has to bark, moo or meow, so how do we do that in typescript?
Let's set an example:
type Cat = {
name: string;
meow: () => void;
}
type Dog = {
name: string;
bark: () => void;
};
type Cow = {
name: string;
moo: () => void;
};
We have 3 types here: Cat,
Dog
and Cow
. They all share the name
property, but what makes them unique is their capabilities of giving sound; this is the bark
property for Dogs, meow
for cats, and moo
-ing for the cow.
Let's initialize our animals:
const rex: Dog = {
name: 'Rex',
bark: () => {
console.log('๐ถ Woof ๐ถ');
}
};
const mrBubbles: Cat = {
name: 'Mr. Bubbles',
meow: () => {
console.log('๐ MEOW ๐')
}
};
const helga: Cow = {
name: 'Helga',
moo: () => {
console.log('๐ฎ Moo ๐ฎ')
}
};
We've given them names and unique voices (since every dog bark sounds different).
Making a difference by the animal sound
So we create a function called makeSound
which makes the animal well... sound:
const makeSound = (animal: Dog | Cat | Cow) => { }
Now, if we want to distinguish which animal is making a sound, we need functions to tell which animal it is:
const isCat = (animal: Dog | Cat | Cow): animal is Cat => {
return (animal as Cat).meow !== undefined;
}
const isDog = (animal: Dog | Cat | Cow): animal is Cow => {
return (animal as Dog).bark !== undefined;
}
const isCow = (animal: Dog | Cat | Cow): animal is Cow => {
return (animal as Cow).moo !== undefined;
}
The return statement of animal is Cat
, for example, expects a boolean value. This value tells typescript if this animal
is a Cat
. The meow
property makes an animal a Cat
, so that's why we check if that is not undefined
.
Let's make them give their sound
To use this, we have to call it with our variable, and typescript knows which type we're operating with:
const makeSound = (animal: Dog | Cat | Cow) => {
if (isCat(animal)) {
animal.meow();
} else if (isCow(animal)) {
animal.moo();
} else {
animal.bark();
}
}
makeSound(rex); // => ๐ถ Woof ๐ถ
makeSound(helga); // => ๐ฎ Moo ๐ฎ
makeSound(mrBubbles); // =>๐ Meow ๐
Other types of usages
Usually, we would see animals in some array like this:
const animals = [rex, mrBubbles, helga];
But now we have to make only the dogs bark, how do we do that? Well, we can filter out only the dogs with our method.
const onlyDogs: Dog[] = animals.filter((animal) => isDog(animal));
Conclusion
I hope this short tutorial helped you explain how to differentiate between types in Typescript.
If you like what I'm writing, leave a comment and let me know if it was helpful!
Thanks for reading! ๐