User-Defined Type Guards
Notice that we had to use type assertions several times. It would be much better if once we performed the check, we could know the type of pet
within each branch.
It just so happens that TypeScript has something called a type guard. A type guard is some expression that performs a runtime check that guarantees the type in some scope. To define a type guard, we simply need to define a function whose return type is a type predicate:
function isFish(pet: Fish | Bird): pet is Fish { return (<Fish>pet).swim !== undefined; }
pet is Fish
is our type predicate in this example. A predicate takes the form parameterName is Type
, where parameterName
must be the name of a parameter from the current function signature.
Any time isFish
is called with some variable, TypeScript will narrow that variable to that specific type if the original type is compatible.
// Both calls to 'swim' and 'fly' are now okay. if (isFish(pet)) { pet.swim(); } else { pet.fly(); }
Notice that TypeScript not only knows that pet
is a Fish
in the if
branch; it also knows that in the else
branch, you don’t have a Fish
, so you must have a Bird
.
Please login to continue.