Nov 26, 2018

Using TypeScript Type Guard to Narrow Down Type

Update: This article is outdated. With the introduction of inferred type predicate in TypeScript 5.5, TypeScript can correctly infer the type predicate without us needing to explicitly type it.


Typescript is aware of usage of the Javascript instanceof and typeof operators, and will narrow down the type accordingly when you use those operators in conditional block.

function doSomething(x: number | string) {
  if (typeof x === 'string') {
    // Within the block TypeScript knows that `x` must be a string
    console.log(x.substr(1));
  }
  x.substr(1);
Property 'substr' does not exist on type 'string | number'. Property 'substr' does not exist on type 'number'.
}

(Example stolen from Typescript Deep Dive)

Usually, those typechecking are used frequently, and you may want to create some utility function to abstract it away. However, with those abstraction, you lose the narrowing down of typescript.

const isString = (value: any) => typeof value === 'string';

function doSomething(x: number | string) {
  if (isString(x)) {
    // Typescript doesn't know that x must be a string
    console.log(x.substr(1)); // Error
  }
}

Solution: Custom Type Guard

Typescript introduces the concept of custom type guard, which allows you to create utility function that assert the type of the parameters.

function isString(value: any): value is string {
  return typeof value === 'string';
}

function doSomething(x: number | string) {
  if (isString(x)) {
    console.log(x.substr(1)); // OK
  }
}

Side Note: npm package for common type checking

I’ve published a npm package, typesafe-is that consists of common type-checking with typeguard, as those are required in almost are javascript applications.

Thanks for reading!

Love what you're reading? Sign up for my newsletter and stay up-to-date with my latest contents and projects.

    I won't send you spam or use it for other purposes.

    Unsubscribe at any time.