TypeScript
03 / 18

Type Guards & Narrowing

TypeScript Type Guards & Narrowing

Type Narrowing

// typeof narrowing
function padLeft(value: string, padding: string | number) {
  if (typeof padding === 'number') {
    return ' '.repeat(padding) + value;
  }
  return padding + value;
}

// Truthiness narrowing
function printAll(strs: string | string[] | null) {
  if (strs && typeof strs === 'object') {
    // TypeScript knows strs is string[]
    for (const s of strs) {
      console.log(s);
    }
  } else if (typeof strs === 'string') {
    console.log(strs);
  }
}

// Equality narrowing
function example(x: string | number, y: string | boolean) {
  if (x === y) {
    // x and y must both be string
    x.toUpperCase();
    y.toUpperCase();
  }
}

// in operator narrowing
type Fish = { swim: () => void };
type Bird = { fly: () => void };

function move(animal: Fish | Bird) {
  if ('swim' in animal) {
    animal.swim();
  } else {
    animal.fly();
  }
}

// instanceof narrowing
function logValue(value: Date | string) {
  if (value instanceof Date) {
    console.log(value.toUTCString());
  } else {
    console.log(value.toUpperCase());
  }
}

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free