Type Guards in TypeScript: How to Narrow Down Types with Conditionals
TypeScript is a powerful language that compiles to JavaScript and adds static type-checking along with other features. One of the most useful features of TypeScript is the ability to narrow down a type using Type Guards. In this post, we will learn how to use Type Guards to narrow down types with conditionals.
Type Guards are a way of narrowing down a type in TypeScript. They are used to determine if a variable is of a certain type at runtime. This is useful when dealing with union types or when you want to ensure that a variable is of a specific type before performing an operation on it.
Type Guards are implemented using conditionals. These conditionals can be simple or complex, depending on the use case.
Type Guards can be implemented using the typeof
operator, instanceof
operator, or custom type predicates.
The typeof
operator can be used to narrow down a type based on the type of value it holds. For example, let's say we have a variable x
that can hold either a number or a string:
let x: number | string = 5;
We can use the typeof
operator to determine if x
is a number or a string:
if (typeof x === 'number') {
// x is a number
} else {
// x is a string
}
The instanceof
operator can be used to narrow down a type based on its constructor function. For example, let's say we have a class Person
:
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
We can create an instance of Person
and then use the instanceof
operator to determine if it is an instance of Person
:
let p = new Person('John', 30);
if (p instanceof Person) {
// p is an instance of Person
} else {
// p is not an instance of Person
}
A custom type predicate is a function that returns a boolean value and is used to determine if a variable is of a certain type. For example, let's say we have a type Car
:
interface Car {
make: string;
model: string;
year: number;
}
We can create a custom type predicate to determine if a variable is of type Car
:
function isCar(obj: any): obj is Car {
return (
typeof obj === 'object' &&
'make' in obj &&
'model' in obj &&
'year' in obj
);
}
We can then use this custom type predicate to determine if a variable is of type Car
:
let myCar = { make: 'Honda', model: 'Civic', year: 2010 };
if (isCar(myCar)) {
// myCar is of type Car
} else {
// myCar is not of type Car
}
Type Guards are a powerful feature of TypeScript that can help ensure type safety in your code. They are particularly useful when dealing with union types or when you want to ensure that a variable is of a specific type before performing an operation on it.
It is important to note that Type Guards only work at runtime and not at compile time. Therefore, it is important to test your code thoroughly to ensure that it is working correctly.
Type Guards are an essential feature of TypeScript that can help ensure type safety in your code. They are easy to use and can be implemented using simple or complex conditionals. By using Type Guards, you can be confident that your code is working correctly and that it is type-safe.