
Unlocking Safer, More Robust Code Through Advanced Type Checking
Introduction
Type guards in TypeScript function as safety checks. They help ensure you’re dealing with the exact type you expect, making them invaluable for dealing with complex data structures or various types.
User-Defined Type Guards
Create custom type guards using functions that return type confirmations based on the is
keyword.
function isHotel(place: unknown): place is Hotel {
return (place as Hotel).propertyType === 'Hotel';
}
interface Hotel {
propertyType: 'Hotel';
rooms: number;
amenities: string[];
}
const accommodation: unknown = { propertyType: 'Hotel', rooms: 120, amenities: ['pool', 'gym'] };
if (isHotel(accommodation)) {
console.log(`This hotel has ${accommodation.rooms} rooms.`);
}
Generics in Type Guards
Sometimes you might want a more flexible type guard, one that works across various types. Generics come in handy here.
function isType<T>(val: unknown, check: (arg: unknown) => boolean): val is T {
return check(val);
}
const isNumber = (val: unknown): val is number => typeof val === 'number';
if (isType<number>(42, isNumber)) {
console.log("It's a number!");
}
Discriminated Unions
Consider the example of a booking system that features various types of accommodations, such as hotels, hostels, or Airbnb listings.
interface Hotel {
kind: 'hotel';
rooms: number;
}
interface Hostel {
kind: 'hostel';
beds: number;
}
interface Airbnb {
kind: 'airbnb';
bedrooms: number;
}
type Accommodation = Hotel | Hostel | Airbnb;
function getCapacity(accommodation: Accommodation): number {
switch (accommodation.kind) {
case 'hotel':
return accommodation.rooms;
case 'hostel':
return accommodation.beds;
case 'airbnb':
return accommodation.bedrooms;
default:
const _exhaustiveCheck: never = accommodation;
return _exhaustiveCheck;
}
}
Extended Discriminated Unions
In a more complicated scenario, let’s consider different amenities offered by Hotels, Hostels, and Airbnb listings. Discriminated Unions can be extremely helpful to handle such diversity.
interface Hotel {
kind: 'hotel';
rooms: number;
gym: boolean;
}
interface Hostel {
kind: 'hostel';
beds: number;
communalKitchen: boolean;
}
interface Airbnb {
kind: 'airbnb';
rooms: number;
entirePlace: boolean;
}
type Accommodation = Hotel | Hostel | Airbnb;
function listAmenities(accommodation: Accommodation): string[] {
switch (accommodation.kind) {
case 'hotel':
return [`Rooms: ${accommodation.rooms}`, `Gym: ${accommodation.gym ? 'Yes' : 'No'}`];
case 'hostel':
return [`Beds: ${accommodation.beds}`, `Communal Kitchen: ${accommodation.communalKitchen ? 'Yes' : 'No'}`];
case 'airbnb':
return [`Rooms: ${accommodation.rooms}`, `Entire Place: ${accommodation.entirePlace ? 'Yes' : 'No'}`];
default:
const _exhaustiveCheck: never = accommodation;
return _exhaustiveCheck;
}
}
listAmenities({ kind: 'hostel', 'beds': 10, communalKitchen: false })
// ERROR: Object literal may only specify known properties, and 'entirePlace' does not exist in type 'Hostel'
listAmenities({ kind: 'hostel', 'beds': 10, entirePlace: true })
Using in
and instanceof
Keywords
The in
keyword checks for the existence of a property within an object, while instanceof
is used for identifying an object's class.
// Checking with 'in'
if ('rooms' in accommodation) {
// Do something with accommodation.rooms
}
// Checking with 'instanceof'
class BoutiqueHotel {
quality: string = "high";
}
const myHotel = new BoutiqueHotel();
if (myHotel instanceof BoutiqueHotel) {
console.log(myHotel.quality); // Outputs "high"
}
The Dark Side of Loose Typing
Using loose types like any
in TypeScript may seem convenient, but it comes with risks, especially in complex systems like booking platforms. It makes your code harder to debug and maintain, undoing some of the benefits of using TypeScript in the first place.
Closing Thoughts
There you go. A deep dive into type guards in TypeScript. These tools offer a robust way to manage complex types in your applications. Stay tuned for our next topic; catch you then!

Become a subscriber receive the latest updates in your inbox.
Member discussion