TypeScript Type Guards, a quick introduction

Note Statistics

Note Statistics

  • Viewed 170 times
Sun, 12/27/2020 - 15:37

Type guards are a way to check the type of a variable. Specifically a way for the compiler to narrow the type of a variable. This help the compiler check for errors.

There 3 major types

  • typeof
  • instanceof
  • user defined

Let's look at examples

typeof type guard

let num = string | number; 

if(typeof num === 'number') {
  // x is a number. we can can any number methods without getting errors from the compiler
}

In the snippet above the variable num could be of 2 types, string or number. To perform certain operation to this variable we might need to know the type before performing the operation. In this case be we use a typeof type guard using a if statement. Inside the if block the type of num is narrowed down to number.

Note This type is limited to string, boolean, number and symbol types.

instanceof type guard

Similar to typeof type guard, the instanceof type guard is used to narrow down class instances. Let use an example.

class Dog {
  bark() {
    console.log('Woof');
  }
}

class Cat {
  meow() {
    console.log('Meow');
  }
}

type HousePet = Cat | Dog;

function callOwner(pet: HousePet): void {
  if (pet instanceof Dog) {
    pet.bark();
  } else {
    pet.meow();
  }
}

In the snippet above the argument pet of the callOwner function could be of two types, Dog or Cat. Here two types guard are used to detect the type of the pet before calling the associated method. The if block us used to check the Dog type while else block infers that we have a Cat.

User defined type guards

These type guards can be used to check interfaces. To implement user defined type guards we need to implement a function. This function is special because it's signature is different than regular function. This return of this function is called a type predicate. The type predicate has

  • the name of the parameter parameter
  • followed by 'is'
  • followed by the type of the we are checking

Lets look at an example.

interface Car {
   horsePower: number;
}

interface Plane {
   wings: number;
}

function isCar( c: Car | Plain) c is Car {
  return (c as Car).horsePower !== undefined;
} 

In the snippet above, we wrote a type guard that checks that a variable is of type Car. This function requires 3 things

  1. a parameter to check
  2. The type predicate
  3. The body of the function perform a check an returns true if the parameter is of the wanted type, otherwise returns false.
Authored by
Tags