Custom Errors in JavaScript and when to use them?

Custom Errors in JavaScript and when to use them?

They're more useful than you think.

Introduction

I recently came across custom errors in JavaScript. I was surprised I hadn't seen them before. They can be extremely useful when building larger systems and wanting to provide a good user experience.

How to

You create a class that extends the built-in Error class. This custom class can have additional properties or methods as needed.

class MyCustomError extends Error {
   constructor(message) {
      super(message);
      this.name = 'MyCustomError';
      // Custom logic or additional properties
   }
}

When are they useful

From my experience, custom error classes are useful in two situations:

  • Provide the user with a specific error message.

  • Be specific when logging the error.

    • Logging here refers to observability.

Example

Here we have a quick example with DatabaseError . It has both the name and operation. Let's say, for instance, you have a type-safe logging library with different names and operations.

You could do something like this for database errors.

Other types of errors would definitely have the name, but maybe not the operation. I guess it depends on the context.

It's nice because of how specific we can be when logging or returning error messages back to the user.

class DatabaseError extends Error {
    constructor(message, operation) {
        super(message);
        this.name = 'DatabaseError';
        this.operation = operation;
    }
}

// Example usage
try {
    // Simulating a database operation failure
    throw new DatabaseError('Failed to execute SQL query', 'query');
} catch (error) {
    if (error instanceof DatabaseError) {
        // Using the external logging library
        loggingLibrary.log({
            level: 'error',
            message: error.message,
            errorName: error.name,
            operation: error.operation,
            timestamp: new Date().toISOString(),
            stack: error.stack
        });
    } else {
        // Handle other types of errors
    }
}