#typescript
#types
#advanced
Day 17: Type Guards and Narrowing
Runtime Checks
Welcome to Day 17! We know how to define types. But how do we check them when the code is actually running? This is called Type Narrowing.
Built-in Guards
We’ve already seen typeof.
function padLeft(padding: number | string, input: string) {
if (typeof padding === "number") {
return " ".repeat(padding) + input; // padding is number here
}
return padding + input; // padding is string here
}
We also have instanceof for classes.
if (x instanceof Date) {
console.log(x.getTime());
}
Custom Type Predicates (is)
What if we want to check an interface? typeof only checks primitives. We can write a custom function that returns a Type Predicate.
interface Fish { swim: () => void; }
interface Bird { fly: () => void; }
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
The magic is pet is Fish. If the function returns true, TypeScript knows pet is a Fish.
function move(pet: Fish | Bird) {
if (isFish(pet)) {
pet.swim(); // OK
} else {
pet.fly(); // OK (must be Bird)
}
}
Challenge for Today
- Define interfaces
Car(drive) andBoat(sail). - Write a Type Guard function
isCar. - Create a function that takes
vehicle: Car | Boat. - Use your type guard to call the correct method.
See you on Day 18 for the elegant Discriminated Unions!