Custom Type Guards in TypeScript

Custom Type Guards in TypeScript

ยท

2 min read

My previous post showed with some short code snippets 5 useful TypeScript ticks. One of those tricks was a User-Defined Type Guard. Since this "trick" has attracted a lot of attention, I decided to write this short post to make this concept easier to understand.

What are Type Guards

A Type Guard reduces the type of an object in a conditional block. The most known Type Guards are the famous typeof and instanceof operators.

Different Type Guards

  • typeof
  • instanceof
  • in
  • Literal Type Guard
  • null and undefined with strictNullChecks
  • User-Defined Type Guards

Creating a User-Defined Type Guard

Unfortunately one can quickly feel the limits of the basic Type Guards when e.g. working with plain JavaScript objects.

Below an example of a user defined Type Guard.


interface IApple{
    name: string;
    color: string;
}

interface IBanana{
    name: string;
    size: number;
}

type Fruit = IApple | IBanana;

/** Custom Type Guard */
const isApple = (f: Fruit): f is IApple => {
    return (f as IApple).color !== undefined
}

const apple: Fruit = {name: "Pink Pearl", color: "red"};
const banana: Fruit = {name: "Cavendish", size: 20};

console.log(isApple(apple)) // Logs true
console.log(isApple(banana)) // Logs false

f is IApple is a type predicate. With this, instead of just returning a boolean, TypeScript will reduce the type to IApple. In the following code TypeScript will understand that inside the condition apple is an IApple.

if(isApple(apple)){
    /** TS undestands that apple is an IApple */
    console.log(apple.color); // Logs red
}

This is the big advantage of using User-Defined Type Guards. Be aware that a wrongly coded Type Guards can introduce major errors into your code.

More about Type Guards