How does type narrowing work in TypeScript?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
TypeScript narrows union types automatically through control-flow analysis: typeof checks, truthiness, instanceof, the in operator, equality checks against literals, and user-defined type guards (is) all refine types within branches.
Detailed explanation
Narrowing is TypeScript inferring a more specific type from runtime checks. typeof x === 'string' refines to string inside the branch (with caveats for null and functions); truthiness drops falsy members; instanceof uses constructor classes; 'prop' in obj distinguishes union members structurally; comparing against literal values pins discriminated-union tags. The else branch gets the complement — exclusivity flows both ways. For logic TS can't infer — Array.isArray-style checks, parsing results — write user-defined guards: function isError(e: unknown): e is ApiError { ... } returns a boolean while teaching the compiler the refined type. Assertion functions (asserts x is T) throw instead of returning. Discriminated unions with a kind/tag literal plus switch statements produce the cleanest narrowing flow and are the recommended modeling approach for complex state.
Example
type ApiResponse =
| { status: 'success'; data: string[] }
| { status: 'error'; message: string };
function handle(res: ApiResponse) {
switch (res.status) { // discriminant narrows both branches
case 'success':
console.log(res.data.length); // res is success variant
break;
case 'error':
console.error(res.message); // res is error variant
break;
}
}
const isStringArray = (v: unknown): v is string[] =>
Array.isArray(v) && v.every(x => typeof x === 'string');Interview tip
Walk one discriminated union through a switch end-to-end, then define custom guards (e/is) — that covers the entire narrowing toolbox concisely.
Common mistakes
- Casting with as everywhere instead of writing proper guards.
- Not knowing
innarrows based on property presence.