A memo on TypeScript narrowing
I use narrowing daily but still pause to pick the right tool.
Three common shapes
// 1. Primitives: typeof
function pad(x: string | number) {
if (typeof x === "string") return x.padStart(8, "0");
return String(x).padStart(8, "0");
}
// 2. Object shapes: in
function area(s: { r: number } | { w: number; h: number }) {
if ("r" in s) return Math.PI * s.r ** 2;
return s.w * s.h;
}
// 3. Best: discriminated unions
type Shape =
| { kind: "circle"; r: number }
| { kind: "rect"; w: number; h: number };
Pair a discriminated union with switch and a never fallback, and the compiler warns you when a new variant isn't handled — that's the real win.