Narrow discriminated object unions
A union contains structurally distinct object variants and a reusable property-based check is needed.
TypeScript · Function
Type predicates let custom boolean functions tell TypeScript how to narrow a value. A return type like value is Widget makes a successful call refine the argument to Widget.
A type predicate is a return-type annotation such as value is SomeType that connects a boolean runtime check to TypeScript's control-flow narrowing. When the function is called and returns true, the checked argument is treated as the predicate type in the relevant scope; methods can similarly use this is Type.
function predicate(parameterName: OriginalType): parameterName is NarrowedType { /* runtime check */ }| Name | Type | Description |
|---|---|---|
parameterName | original type compatible with Type | The value being checked; its name must be used before is in the predicate return type. |
A boolean result annotated as a type predicate, such as parameterName is Type; a true result narrows the argument to Type.
is, and the type that should be known after a successful check.this.is must refer to a parameter of that same function; an unrelated variable name cannot be used.type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Pet = Fish | Bird;
function isFish(pet: Pet): pet is Fish {
return "swim" in pet;
}
function move(pet: Pet) {
if (isFish(pet)) pet.swim();
else pet.fly();
}
move({ swim() {} });The predicate tells TypeScript that a true result means the argument is a Fish, so control-flow analysis narrows the union inside the corresponding branch.
A union contains structurally distinct object variants and a reusable property-based check is needed.
A collection contains mixed values and a reusable guard should produce a more precise filtered result.
A class needs to expose a check that refines the receiver's type.
A type predicate is a return type with the form parameterName is Type. It lets a user-defined function communicate a runtime-tested type to TypeScript's control-flow analysis, so a true call narrows the argument.
Follow-up: Can a method narrow its receiver? Yes: a class or interface method can return this is Type, which narrows the object on a successful check.
The predicate must name a parameter from the current function signature, and its target type describes the narrowed form. For example, pet is Fish means a true result lets TypeScript treat the supplied pet as Fish.
Follow-up: What happens when the argument is not compatible with the target type? The predicate does not provide the intended useful narrowing for that argument, because the documented narrowing applies when the original type is compatible.
A predicate function still performs an ordinary runtime check; the annotation supplies the type information that the checker cannot derive from a general custom function by itself. Calling it in a narrowing position lets TypeScript follow the result and refine the value.
Follow-up: How can built-in checks reduce the need for a custom predicate? Operators such as typeof, in, and instanceof are recognized narrowing expressions and can narrow compatible union members directly.
type guardnarrowingtypeof type guardsin operatorinstanceofthis is Type