Type Guards in TypeScript (Live Playground)
In this tutorial, we will explore type guards in TypeScript, which are essential for safely handling different types in your code.
What are Type Guards?
Type guards are expressions that perform a runtime check to determine the type of a variable. They help TypeScript to narrow down the type of a variable within a specific scope, making it easier to work with different types safely.
Using typeof for Type Guards
The typeof
operator can be used as a type guard for basic types such as string
, number
, boolean
, and object
.
function log(value: string | number): void {
if (typeof value === 'string') {
console.log(`String: ${value}`);
} else {
console.log(`Number: ${value}`);
}
}
log('TypeScript'); // String: TypeScript
log(42); // Number: 42
Using instanceof for Type Guards
The instanceof
operator can be used as a type guard for custom types, such as classes.
class Circle {
constructor(public radius: number) {}
}
class Rectangle {
constructor(public width: number, public height: number) {}
}
function log(shape: Circle | Rectangle): void {
if (shape instanceof Circle) {
console.log(`Circle with radius ${shape.radius}`);
} else {
console.log(`Rectangle with dimensions ${shape.width}x${shape.height}`);
}
}
log(new Circle(5)); // Circle with radius 5
log(new Rectangle(10, 20)); // Rectangle with dimensions 10x20
User-Defined Type Guards
User-defined type guards are functions that return a type predicate, allowing you to create custom type checks that can be used with TypeScript's type narrowing capabilities.
You can also create custom type guards by defining a function that returns a type predicate.
interface Circle {
kind: 'circle';
radius: number;
}
interface Rectangle {
kind: 'rectangle';
width: number;
height: number;
}
function isCircle(shape: Circle | Rectangle): shape is Circle {
return shape.kind === 'circle';
}
function log(shape: Circle | Rectangle): void {
if (isCircle(shape)) {
console.log(`Circle with radius ${shape.radius}`);
} else {
console.log(`Rectangle with dimensions ${shape.width}x${shape.height}`);
}
}
log({ kind: 'circle', radius: 5 }); // Circle with radius 5
log({ kind: 'rectangle', width: 10, height: 20 }); // Rectangle with dimensions 10x20
In the example above, we define a isCircle
function that checks whether a given shape
is of type Circle
. The shape is Circle
part of the function signature is the type predicate.
Conclusion
In this tutorial, we have explored type guards in TypeScript, which are essential for safely handling different types in your code. As you continue learning TypeScript, make sure to practice using type guards to ensure your code remains safe and efficient while working with different types.