typeof and Truthiness Narrowing

typeof Guards

Narrowing is how TypeScript turns a wide type (like string | number) into a specific one inside a branch, by following your if checks. typeof works for primitives: "string", "number", "boolean", "bigint", "symbol", "undefined", "function", "object".

Example

function formatAmount(value: string | number | bigint): string {
  if (typeof value === "string") return value.trim();       // string
  if (typeof value === "bigint") return value.toString() + "n"; // bigint
  return value.toFixed(2);                                   // number
}

console.log(formatAmount("  499 "));
console.log(formatAmount(499));
console.log(formatAmount(499n));

Output

499
499.00
499n

Truthiness Narrowing

Example

An if (value) check removes null and undefined. Careful: it also removes 0 and "", which are often valid values.

function greet(name?: string | null): string {
  if (name) return "Hi " + name.toUpperCase();
  return "Hi guest";
}

function stockLabel(stock: number | null): string {
  if (!stock) return "unknown";          // BUG: 0 becomes "unknown"
  return stock + " left";
}
function stockLabelFixed(stock: number | null): string {
  if (stock === null) return "unknown";
  return stock + " left";
}

console.log(greet("meera"), "|", greet(null));
console.log(stockLabel(0), "|", stockLabelFixed(0));

Output

Hi MEERA | Hi guest
unknown | 0 left

typeof null is "object"

Note: typeof null === "object" is a famous JavaScript quirk. TypeScript knows it, so after typeof x === "object" the type still includes null. Add x !== null.