Skip to main content

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.

TypeScript
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
Live Playground, Try it Yourself

Using instanceof for Type Guards

The instanceof operator can be used as a type guard for custom types, such as classes.

TypeScript
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
Live Playground, Try it Yourself

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.

TypeScript
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.

Live Playground, Try it Yourself

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.