BeCuriouzLearn something new every day
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.
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.