Custom errors in JavaScript
By Flavio Copes
Learn how to create custom errors in JavaScript by extending the built-in Error class, then handle each type with instanceof for cleaner error handling.
To create a custom error in JavaScript, you define a class that extends the built-in Error class. You can then throw it like any other error, and recognize it with instanceof when you catch it.
JavaScript gives us a set of built-in error objects, raised depending on the error type:
ErrorAggregateErrorEvalErrorRangeErrorReferenceErrorSyntaxErrorTypeErrorURIError
I analyzed them all in the JavaScript errors tutorial.
Those cover the errors JavaScript itself raises. But your application has its own failure cases, and a generic Error with a message string can’t tell them apart in code.
How do you create a custom error?
Extend the base Error class:
class OutOfFuelError extends Error {}
class FlatTireError extends Error {}
An empty class body is enough. Each class is now a distinct error type, and instances are still real errors: err instanceof Error is true, and you get a stack trace for free.
Throwing and catching custom errors
Custom errors allow you to behave differently based on the specific error type, without resorting to error messages to understand the kind of error:
try {
const car = new Car() //imagine we have a Car object
if (!car.fuel) {
throw new OutOfFuelError('No fuel!')
}
if (car.flatTire) {
throw new FlatTireError('Flat tire!')
}
} catch (err) {
if (err instanceof OutOfFuelError) {
//handle error
} else if (err instanceof FlatTireError) {
//handle error
} else {
throw err
}
}
Notice the final else that rethrows. Without it, any other error raised inside the try block (a TypeError from a typo, for example) gets silently swallowed, and you’ll spend a long time wondering why nothing happens. Handle the errors you know, rethrow the rest.
Setting the error name
By default the name property of your custom error is still Error, which makes logs confusing:
const err = new OutOfFuelError('No fuel!')
console.log(err.name) //'Error'
console.log(String(err)) //'Error: No fuel!'
Fix it in the constructor:
class OutOfFuelError extends Error {
constructor(message) {
super(message)
this.name = 'OutOfFuelError'
}
}
Now the same log prints OutOfFuelError: No fuel!, which tells you what happened at a glance.
Adding custom properties
Since it’s a regular class, you can attach any data the handler might need:
class OutOfFuelError extends Error {
constructor(message, kmToNearestStation) {
super(message)
this.name = 'OutOfFuelError'
this.kmToNearestStation = kmToNearestStation
}
}
throw new OutOfFuelError('No fuel!', 12)
The catch block can read err.kmToNearestStation and decide what to do, instead of parsing that value out of a message string.
Related posts about js: