Lesson 20 / 26

Type Guards

Narrow a broad type down to a specific one using runtime checks.

typeof narrowing

Inside an if (typeof x === "string") block, TS knows x is a string for the rest of that branch.

function printId(id: string | number) {
  if (typeof id === "string") {
    console.log(id.toUpperCase()); // id is string here
  } else {
    console.log(id.toFixed(2));    // id is number here
  }
}

instanceof narrowing

For classes, instanceof narrows a union of class types down to the matching one.

class Cat { meow() { return "Meow!"; } }
class Dog { bark() { return "Woof!"; } }

function speak(pet: Cat | Dog) {
  if (pet instanceof Cat) {
    console.log(pet.meow());
  } else {
    console.log(pet.bark());
  }
}

Why narrow at all?

A union type only exposes the properties common to every member. Narrowing proves to the compiler which member you actually have, unlocking its specific properties and methods.

Quick check: Inside `if (typeof id === "string") { ... }`, what type does TS assign to `id`?

  • string | number, unchanged
  • string
  • any
Answer

string — The typeof check narrows the union to just string inside that block.