BeCuriouzBeCuriouz

Learn something new every day

🔷 TypeScript
🔎

typeof & Truthiness: How TypeScript Narrows

💡 TypeScript narrows a union to a specific type inside a branch whenever it sees a check it understands — typeof for primitive types and truthiness for filtering out falsy values.

Recall that a union type like string | number means a value could be either type. But you can't call .toUpperCase() on a number, so TypeScript won't let you use string-only methods until it knows which type you actually have right now. Narrowing is how the compiler shrinks a broad type to a more specific one inside a branch of code, based on checks you write. The two simplest triggers are typeof and plain truthiness.

A typeof guard is a runtime check TypeScript recognizes at compile time. When you write if (typeof x === 'string'), inside that block TS narrows x from string | number down to just string — so string methods become legal. The else branch gets the leftover number.

ts
function format(x: string | number) {
  if (typeof x === 'string') {
    return x.toUpperCase(); // x is string here
  }
  return x.toFixed(2);      // x is number here
}

A truthiness guard narrows by filtering out falsy values — null, undefined, 0, '', false, and NaN. Writing if (value) removes null and undefined from a string | null union inside the block. Beware the classic trap: typeof null === 'object', so a typeof x === 'object' check keeps null in scope. And a bare if (str) also excludes the empty string '', which is often not what you want when only null should be filtered.

🔎 typeof & Truthiness: How TypeScript Narrows — BeCuriouz