Narrowing means TypeScript changes a broad type into a more specific one inside a branch of your code. It does this because it understands your runtime checks.
TypeScript follows the paths your code can take, through if, return, switch and so on. This is called control flow analysis. For example, inside if (typeof x === "string"), TypeScript knows x is a string.
The main ways to narrow:
typeofchecks for primitives, liketypeof x === "string".instanceoffor class instances, such asDateorError.- The
inoperator to check that a property exists, like"swim" in animal. - Equality checks, including against
nullor a literal value. - Truthiness checks, like
if (user). - Checking a shared literal property on a discriminated union, like
shape.kind === "circle". A discriminated union is a union where each member has the same property with a different literal value. - User-defined type guards. These are functions that return
x is T. - Assertion functions. These return
asserts x is Tand throw if the check fails.
After an early return or throw, the rest of the function also sees the narrowed type.
- Use
typeofto narrow primitives andinstanceofto narrow class instances. - The
inoperator, equality checks and truthiness checks also narrow. - A discriminated union narrows when you check its shared literal property, like
kind. - Custom type guards return
x is T, and assertion functions returnasserts x is T. - Control flow analysis means TypeScript follows your code paths, so an early
returnnarrows the rest of the function.
Read more