User Defined Type Guards in TypeScript
A Type Guard is a technique used to test if a value is of a specific type depending on the boolean returned by a regular function. They prove particularly helpful when working with API responses of uncertain types.
By Vasili Zalimidis —
A Type Guard is a technique used to test if a value is of a specific type depending on the boolean returned by a regular function that contains (usually) a conditional block.
Type guards prove helpful when working with API responses of uncertain types. Developers can create custom type guards to validate data before accessing properties.
let couldBePancake: unknown; // API response retrieved
type Pancake = {
name: string;
variant: 'salty' | 'sweet';
toppings: number;
totalPrice: number;
};
console.log(couldBePancake.name); // Object is of type 'unknown'
This fails because TypeScript cannot confirm the variable matches the Pancake type.
Solution: Type Guard Function
function isPancake(obj: any): obj is Pancake {
return obj.name && obj.variant && obj.toppings && obj.totalPrice;
}
if (isPancake(couldBePancake)) {
console.log(couldBePancake.name); // no errors here
}
Once narrowed through the guard, accessing properties becomes safe.
Type Guards in Callbacks
TypeScript doesn't assume type guards remain active in a callback — making that assumption would be dangerous:
if (isPancake(couldBePancake)) {
calculateTotal(() => {
console.log(couldBePancake.toppings * 1.1 + basePrice); // TS Error
});
}
Workaround: Local Variable
Store the validated value locally before the callback:
if (isPancake(couldBePancake)) {
const numOfToppings = couldBePancake.toppings;
calculateTotal(() => {
console.log(numOfToppings * 1.1 + basePrice); // Works correctly
});
}
TypeScript recognizes that local variables remain stable and cannot be changed externally, so the type narrowing holds inside the callback.