Last updated: Feb 27, 2024
Reading timeยท3 min
To create a custom class that extends from Error
:
Error
object.super()
method in the class's constructor.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()); }
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()
.
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.
CustomError
You have to use the
instanceof
operator if you need to check if a variable stores an instance of CustomError
.
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()); }
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.
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.
You can learn more about the related topics by checking out the following tutorials: