Create custom Class that extends from Error in TypeScript

avatar
Borislav Hadzhiev

Last updated: Jan 21, 2023
3 min

banner

# Create a custom Class that extends from Error in TypeScript

To create a custom class that extends from Error:

  1. Define a new class that extends from the Error object.
  2. Use the super() method in the class's constructor.
  3. Manually adjust the prototype of the new class.
index.ts
export class CustomError extends Error { statusCode = 400; constructor(message: string) { super(message); // ๐Ÿ‘‡๏ธ because we are extending a built-in class Object.setPrototypeOf(this, CustomError.prototype); } getErrorMessage() { return 'Something went wrong: ' + this.message; } } const err = new CustomError('Failed to fetch'); // ๐Ÿ‘‡๏ธ "Failed to fetch" console.log(err.message); console.log(err.statusCode); // ๐Ÿ‘‰๏ธ 400 // ๐Ÿ‘‡๏ธ "Something went wrong: Failed to fetch" console.log(err.getErrorMessage()); // โœ… Use type guard to be able to access properties/methods if (err instanceof CustomError) { console.log(err.statusCode); // ๐Ÿ‘‰๏ธ 400 // ๐Ÿ‘‡๏ธ "Something went wrong: Failed to fetch" console.log(err.getErrorMessage()); }

create custom class that extends from error

We created a CustomError class that extends the Error class.

Whenever you extend a class, you have to call super() before being able to use the this keyword.

We also had to use the Object.setPrototypeOf method, because we are extending a built-in class.

You have to call Object.setPrototypeOf immediately after calling super().

You have to use this approach for any classes that extend built-ins and for any of the subclasses of CustomError.

We are basically manually adjusting the prototype. If you want to read more on why this is needed, check out this section of TypeScript's wiki.

Make sure to call the super() method in the constructor, otherwise, you'd get the Constructors for derived classes must contain a super call error.

# Checking if a variable is an instance of CustomError

You have to use the instanceof operator if you need to check if a variable stores an instance of CustomError.

index.ts
export class CustomError extends Error { statusCode = 400; constructor(message: string) { super(message); // ๐Ÿ‘‡๏ธ because we are extending a built-in class Object.setPrototypeOf(this, CustomError.prototype); } getErrorMessage() { return 'Something went wrong: ' + this.message; } } const err = new CustomError('Failed to fetch'); // โœ… Check if instance of CustomError if (err instanceof CustomError) { console.log(err.statusCode); console.log(err.getErrorMessage()); }

checking if variable is instance of custom error

The instanceof operator serves as a type guard.

If you throw a CustomError in some other place in your code, you need a way to check if the caught error is a CustomError before you can access CustomError specific properties and methods.

This works in the same way as you checking if an error is an instance of the Error object in a catch block.

index.ts
async function getData() { try { await Promise.resolve(24); } catch (err) { // ๐Ÿ‘‰๏ธ err is unknown here // can't access Error specific properties if (err instanceof Error) { console.log(err.message); // ๐Ÿ‘ˆ๏ธ err is now Error } console.log('Unexpected error: ', err); } }

The err variable has a type of unknown in the catch block, so we have to the instanceof operator before we can access the message property.

This is needed because there's no way to be sure that the caught error will be of specific type ahead of time.

Note that any classes that subclass CustomError also need to manually adjust the prototype.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev