Branch on primitive categories with typeof
A variable has a union of primitive types and operations differ by member.
TypeScript · Function
Type guards are runtime checks that TypeScript uses to narrow a value to a more specific type along control-flow paths. Use built-in JavaScript checks or a user-defined predicate for custom object validation.
A type guard is a runtime-checking expression that lets TypeScript refine a value’s declared type along control-flow paths. Built-in checks such as typeof, equality, in, and instanceof narrow unions, while a function returning a type predicate communicates a custom refinement.
function isType(value: UnknownType): value is SpecificType { return /* runtime check */; }| Name | Type | Description |
|---|---|---|
value | unknown or a union type | The value being tested; for a custom predicate, the parameter name appears on the left side of is. |
Built-in guards refine types in control-flow branches; a user-defined guard returns boolean and declares a predicate such as value is Type to communicate the refinement.
type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Animal = Fish | Bird;
function isFish(animal: Animal): animal is Fish {
return "swim" in animal;
}
function move(animal: Animal): void {
if (isFish(animal)) {
animal.swim();
} else {
animal.fly();
}
}
move({ swim: () => console.log("swimming") });The predicate return type tells TypeScript that a true result narrows the argument to Fish.
A variable has a union of primitive types and operations differ by member.
A union’s members differ by a property or discriminant.
A domain-specific runtime check is needed for a structural type.
A class method can validate and refine its own state.
TypeScript treats checks such as typeof, equality, in, and instanceof as type guards and narrows a value on the corresponding control-flow path. The refinement is compile-time, while the check itself follows JavaScript runtime behavior.
Follow-up: How would you narrow a union of structural object types? Use a discriminating property or the in operator, or write a user-defined predicate when the check needs custom logic.
A user-defined guard is a function whose return type is a predicate such as value is Fish. When the function returns true, TypeScript narrows the passed variable to the predicate’s type, provided the original type is compatible.
Follow-up: What constraint applies to the predicate’s left side? It must be the name of a parameter in the current function signature.
typeof checks compare against JavaScript’s recognized result strings, while instanceof uses a constructor’s runtime prototype information. The in operator narrows a union according to whether a property is present.
Follow-up: When should a custom predicate be preferred? Use one when built-in JavaScript checks do not express the object-level validation needed by the program.
Narrowingtypeof type guardsEquality narrowingin operatorinstanceofUser-defined type guardsType predicatesAssertion functions