Narrowing in plain terms
Narrowing is when TypeScript shrinks a broad type to a more specific one inside a branch, based on checks you wrote. After the check, the value carries the narrower type automatically.
Built in guards
- typeof narrows primitives, separating string, number, and boolean.
- instanceof narrows to a class instance.
- A truthiness check removes null and undefined from a union.
- The in operator narrows by testing for a property name.
User defined guards
For complex checks you write a function returning a type predicate, a return type of the form value is Cat. When that function returns true, the compiler narrows the argument to Cat at the call site.
Assertion functions
An assertion function declares that it throws unless a condition holds. After it returns, the value is narrowed for the rest of the scope, which is handy for validating inputs once.
Why it pays off
Narrowing lets you start from a safe wide type, such as unknown, and reach the specific members only after proving the shape, avoiding unsafe casts.
Key idea
Guards prove a value is a specific type so the compiler narrows it and unlocks that type members safely.