TypeScript - Type Guards: A Beginner's Guide
Hello there, future coding superstar! ? I'm thrilled to be your guide on this exciting journey into the world of TypeScript and Type Guards. As someone who's been teaching computer science for many years, I can tell you that understanding type guards is like having a superpower in the TypeScript universe. So, let's dive in and unlock this power together!
What are Type Guards?
Before we jump into the specifics, let's understand what type guards are. Imagine you're a security guard at a fancy party. Your job is to check each guest's invitation and make sure they're allowed in the right areas. Type guards in TypeScript do a similar job - they help the compiler check and narrow down the type of a variable within a certain block of code.
Now, let's explore the three main types of guards we'll be learning about today:
Type Guard | Description |
---|---|
typeof | Checks the type of a variable |
in | Checks if a property exists in an object |
instanceof | Checks if an object is an instance of a class |
The 'typeof' Type Guard in TypeScript
The 'typeof' type guard is like asking, "What kind of thing are you?" It's used to check the type of a variable. Let's look at an example:
function printAll(strs: string | string[] | null) {
if (typeof strs === "object") {
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
} else {
// do nothing
}
}
In this example, we're using typeof
to check if strs
is an object (which includes arrays) or a string. If it's an object, we loop through it. If it's a string, we print it directly.
Here's a fun way to remember this: imagine you're at a pet shop, and you want to know if an animal is a dog or a cat. You might ask, "What type of animal are you?" That's exactly what typeof
does in TypeScript!
The 'in' Type Guard in TypeScript
The 'in' type guard is like asking, "Do you have this feature?" It checks if a property exists in an object. Let's look at an example:
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) {
animal.swim();
} else {
animal.fly();
}
}
In this code, we're checking if the animal
has a swim
property. If it does, we assume it's a Fish and call the swim
method. If not, we assume it's a Bird and call the fly
method.
Think of it like this: if you're trying to figure out if your new pet is a fish or a bird, you might check if it has fins. That's what the 'in' type guard does - it checks for a characteristic property.
The 'instanceof' Type Guard in TypeScript
The 'instanceof' type guard is like asking, "Are you a member of this family?" It checks if an object is an instance of a particular class. Here's an example:
class Bird {
fly() {
console.log("Flying...");
}
}
class Fish {
swim() {
console.log("Swimming...");
}
}
function move(pet: Bird | Fish) {
if (pet instanceof Bird) {
pet.fly();
} else {
pet.swim();
}
}
let myBird = new Bird();
move(myBird); // Output: Flying...
In this example, we're checking if pet
is an instance of the Bird
class. If it is, we call the fly
method. If not, we assume it's a Fish
and call the swim
method.
Imagine you're at a family reunion, and you're trying to figure out if someone is part of the Johnson family. You might ask, "Are you a Johnson?" That's exactly what instanceof
does in TypeScript!
Putting It All Together
Now that we've learned about these three type guards, let's see how we might use them all together:
class Car {
drive() { console.log("Vroom!"); }
}
class Bicycle {
ride() { console.log("Pedal!"); }
}
type Vehicle = Car | Bicycle | string;
function useVehicle(vehicle: Vehicle) {
if (typeof vehicle === "string") {
console.log(`The vehicle is: ${vehicle}`);
} else if (vehicle instanceof Car) {
vehicle.drive();
} else if ("ride" in vehicle) {
vehicle.ride();
} else {
console.log("Unknown vehicle type");
}
}
useVehicle("Skateboard"); // Output: The vehicle is: Skateboard
useVehicle(new Car()); // Output: Vroom!
useVehicle(new Bicycle()); // Output: Pedal!
In this example, we're using all three type guards:
- We use
typeof
to check if the vehicle is a string. - We use
instanceof
to check if it's a Car. - We use
in
to check if it has aride
method (which would indicate it's a Bicycle).
This is like being a super detective, using all your skills to figure out exactly what kind of vehicle you're dealing with!
Conclusion
And there you have it, my coding apprentices! We've journeyed through the land of TypeScript Type Guards, exploring the typeof
, in
, and instanceof
guards. These powerful tools will help you write safer, more predictable code by allowing TypeScript to understand your intentions better.
Remember, using type guards is like having a friendly conversation with your code. You're simply asking it questions to understand it better. So next time you're coding, don't be shy - strike up a chat with your variables using these type guards!
Keep practicing, stay curious, and before you know it, you'll be guarding types like a pro. Until next time, happy coding! ??
Credits: Image by storyset