Type guards narrow unions at runtime. TS recognizes: • typeof (string/number/boolean/bigint/symbol/undefined) • instanceof (classes) • in (property existence) • equality checks / discriminated unions • user-defined predicates: function isX(arg): arg is X Good narrowing avoids unsafe optional chaining and runtime errors. **Why it matters:** • Prevents “cannot read property of undefined” by proving shape before access • Enables IDE autocomplete within narrowed branches • Exhaustive guards with never fail builds when new variants are added
function isUser(value: unknown): value is User { ... }function isUser(value: unknown): value is { id: string; name: string } {
return (
typeof value === "object" &&
value !== null &&
"id" in value &&
typeof (value as any).id === "string"
);
}
function printLength(value: string | string[]) {
if (typeof value === "string") {
console.log(value.length);
} else {
console.log(value.length); // now string[]
}
}
class HttpError extends Error { status = 500; }
function handle(err: unknown) {
if (err instanceof HttpError) {
console.error(err.status);
}
}
Understanding Narrowing & Type Guards is fundamental to mastering TypeScript. Practice with the examples above and experiment with variations to solidify your knowledge.