~/
hackweb.dev
TypeScript Type Guards & Narrowing
Quiz
⌘K
...
~/
/tutorials
/ts/ts-type-guards/edit
~ Contribute
Suggest a correction or improvement. The author reviews it before it goes live.
Loading...
Comment
0 / 300
Typo
Grammar
Broken link
Clarify
Code
en/tutorials/ts/11ts-type-guards
Write
Preview
Diff
# TypeScript Type Guards & Narrowing Type guards narrow union types to specific types, enabling type-safe operations on them. ## typeof Guard `typeof` narrows primitive types: ```typescript function processValue(value: string | number): void { if (typeof value === "string") { console.log(value.toUpperCase()); } else { console.log(value.toFixed(2)); } } ``` ## instanceof Guard `instanceof` narrows based on class constructors: ```typescript class Dog { bark(): void {} } class Cat { meow(): void {} } function handleAnimal(animal: Dog | Cat): void { if (animal instanceof Dog) { animal.bark(); } else { animal.meow(); } } ``` ## Discriminated Unions A literal property acts as a discriminator for automatic narrowing: ```typescript type Circle = { kind: "circle"; radius: number }; type Rectangle = { kind: "rectangle"; width: number; height: number }; type Shape = Circle | Rectangle; function getArea(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "rectangle": return shape.width * shape.height; } } ``` **Tip:** Discriminated unions are the cleanest narrowing pattern. ## Custom Type Guards Use `value is Type` return type to create reusable guards: ```typescript function isString(value: unknown): value is string { return typeof value === "string"; } let value: unknown = "hello"; if (isString(value)) { console.log(value.toUpperCase()); } ``` ## Truthiness and `in` Guards Truthiness narrows null/undefined. `in` checks for property existence: ```typescript function process(value: string | null): void { if (value) { console.log(value.toUpperCase()); } } function move(animal: { swim(): void } | { fly(): void }): void { if ("swim" in animal) { animal.swim(); } else { animal.fly(); } } ``` ## Best Practices - Use discriminated unions for the cleanest type narrowing - Prefer `switch` statements to handle all cases - Use custom type guards for complex type checking - Keep type guards simple — avoid excessive nesting - Use truthiness checks for null/undefined narrowing ## Common Mistakes - Not using discriminated unions when possible - Using `any` instead of type guards - Forgetting a `default` case in switch statements - Confusing type guards with type assertions — guards narrow, assertions override - Not using `value is Type` in custom guard return types
No changes yet
Reset to original
Submit suggestion
cancel