Type guards narrow the type of a value in a conditional branch. Built-in: typeof (primitive types), instanceof (class instances), in (property existence). Discriminated unions use a literal type "tag" field for exhaustive narrowing. Custom type predicates (value is Type) create reusable narrowing functions. The never type and exhaustive checks catch missing union cases at compile time.
Exhaustive type checking with discriminated unions.
Add a kind or type literal field to every variant in a union. TypeScript narrows to the exact variant in a switch/if block — no casting, no unsafe access, catches missing cases.
default: const _: never = value — this line produces a compile error if a new union member is added but not handled. It's your compiler-enforced completeness check.
value as User is an unsafe assertion. isUser(value): value is User is a runtime-verified narrowing. Use type predicates for unknown data, catch(e: unknown), and JSON responses.
Sign in to share your feedback and join the discussion.