Type Guards
Runtime type checking with compile-time benefits
Introduction
In this lesson, you'll learn about type guards in TypeScript. Coming from JavaScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In JavaScript, you're familiar with runtime type checking with compile-time benefits.
TypeScript has its own approach to runtime type checking with compile-time benefits, which we'll explore step by step.
The TypeScript Way
Let's see how TypeScript handles this concept. Here's a typical example:
// TypeScript type guards narrow types
function processValue(value: string | number[] | Date): string | number {
if (typeof value === "string") {
// value is string here
return value.toUpperCase();
}
if (Array.isArray(value)) {
// value is number[] here
return value.length;
}
// value is Date here
return value.toISOString();
}Comparing to JavaScript
Here's how you might have written similar code in JavaScript:
// JavaScript runtime checks
function processValue(value) {
if (typeof value === "string") {
return value.toUpperCase();
}
if (Array.isArray(value)) {
return value.length;
}
if (value instanceof Date) {
return value.toISOString();
}
}You may be used to different syntax or behavior.
typeof narrows primitive types
You may be used to different syntax or behavior.
instanceof narrows class instances
You may be used to different syntax or behavior.
Array.isArray() narrows to arrays
You may be used to different syntax or behavior.
Custom type guards use 'is' keyword
Step-by-Step Breakdown
1. typeof Guards
The typeof operator narrows to primitive types.
function double(value: string | number): string | number {
if (typeof value === "string") {
return value + value; // string concatenation
}
return value * 2; // number multiplication
}2. Custom Type Guards
Create your own type guards with the 'is' keyword.
interface Dog { bark(): void; }
interface Cat { meow(): void; }
function isDog(pet: Dog | Cat): pet is Dog {
return (pet as Dog).bark !== undefined;
}
function speak(pet: Dog | Cat) {
if (isDog(pet)) {
pet.bark(); // TypeScript knows it's a Dog
} else {
pet.meow(); // TypeScript knows it's a Cat
}
}Common Mistakes
When coming from JavaScript, developers often make these mistakes:
- typeof narrows primitive types
- instanceof narrows class instances
- Array.isArray() narrows to arrays
Key Takeaways
- Type guards narrow union types at runtime
- typeof, instanceof, Array.isArray are built-in guards
- Custom guards use the 'is' return type