TypeScript Type Guards
A type guard is a function or expression that TypeScript recognizes as reliably checking a value's type. Beyond typeof and instanceof, you can write your own custom type guard functions.
A custom type guard uses a special return type syntax, `parameterName is Type`, which tells TypeScript to narrow the type of the argument to `Type` wherever the guard returns true.
function isString(value: unknown): value is string {
return typeof value === "string";
}Built-in guards
`typeof`, `instanceof`, and the `in` operator (checking if a property exists on an object) are all built-in ways to narrow types that TypeScript understands automatically.
Custom type guards
You can define a function like `function isFish(pet: Fish | Bird): pet is Fish { ... }`. TypeScript then narrows the type wherever this function is used inside an if condition.
function isString(value: unknown): value is string {
return typeof value === "string";
}
function printIfString(value: unknown) {
if (isString(value)) {
console.log(value.toUpperCase());
}
}
printIfString("hi");HIisString is a custom type guard; TypeScript narrows value to string inside the if block.
interface Fish { swim(): string; }
interface Bird { fly(): string; }
function isFish(pet: Fish | Bird): pet is Fish {
return "swim" in pet;
}
function move(pet: Fish | Bird) {
if (isFish(pet)) {
console.log(pet.swim());
} else {
console.log(pet.fly());
}
}
move({ swim: () => "Swimming" });SwimmingThe `in` operator checks for the swim property, and isFish narrows the union accordingly.
Key points
- Type guards are checks that TypeScript uses to narrow types.
- Built-in guards include typeof, instanceof, and the in operator.
- Custom type guards use the `parameter is Type` return syntax.
- Type guards make working with union types safer and clearer.
