How do you build a custom error class?
You extend the built-in Error class, call its constructor with the message, and set the name property so that the error identifies itself correctly in logs and in catch blocks.
class ValidationError extends Error {
constructor(field, message) {
super(message);
this.name = "ValidationError";
this.field = field;
this.isValidationError = true;
}
}
try {
throw new ValidationError("email", "That address is not valid");
} catch (err) {
console.log(err instanceof Error); // true
console.log(err instanceof ValidationError); // true
console.log(err.name); // "ValidationError"
console.log(err.field); // "email"
console.log(err.message); // "That address is not valid"
}The super call is not optional. The Error constructor sets up the message and the stack, and if you skip it the error will have no useful message and no stack trace at all. Calling it first, before you touch this, is also required by the language when you are extending a built-in class.
Setting the name matters because that is what the catch block and the log formatter read. The name property on the Error prototype is inherited as Error, so a subclass that does not set it will be reported as a plain Error and you lose the ability to tell your error types apart at runtime.
The extra properties are your own domain data. The field in the example is what makes the error useful in a form handler, where you can put the message next to the right input. You can also add a status code, a machine readable code, or a list of problems, and the catch block can then decide what to do based on those rather than by matching on the message text.