Custom Error Types and Error Handling

Difficulty: Intermediate

Question

What are the built-in error types in JavaScript? How do you create custom error classes?

Answer

Built-in error types: - Error: base class - TypeError: wrong type (calling non-function, accessing property on null) - ReferenceError: accessing undeclared variable - SyntaxError: invalid JavaScript syntax (parse time) - RangeError: value out of allowed range - URIError: malformed URI - EvalError: legacy eval() errors

Custom errors: extend Error class for semantic error handling, adding custom properties, and enabling instanceof checks in catch blocks.

Code examples

Custom Error Classes

class AppError extends Error {
  constructor(message, code, statusCode = 500) {
    super(message);
    this.name = this.constructor.name;
    this.code = code;
    this.statusCode = statusCode;
    Object.setPrototypeOf(this, new.target.prototype);
  }
}

class ValidationError extends AppError {
  constructor(field, message) {
    super(message, 'VALIDATION_ERROR', 400);
    this.field = field;
  }
}

class NotFoundError extends AppError {
  constructor(resource) {
    super(`${resource} not found`, 'NOT_FOUND', 404);
  }
}

try {
  throw new ValidationError('email', 'Invalid email format');
} catch (e) {
  console.log(e instanceof ValidationError);
  console.log(e instanceof AppError);
  console.log(e.name);
  console.log(e.field);
  console.log(e.statusCode);
}

Object.setPrototypeOf fixes the instanceof chain broken in transpiled code. Custom errors allow type-specific handling and rich error metadata.

Error Handling Strategy

async function handleRequest(id) {
  try {
    const user = await fetchUser(id);
    return { success: true, data: user };
  } catch (e) {
    if (e instanceof NotFoundError) {
      return { success: false, message: e.message, statusCode: 404 };
    }
    if (e instanceof ValidationError) {
      return { success: false, field: e.field, statusCode: 400 };
    }
    console.error('Unexpected error:', e);
    throw e;
  }
}

// Global unhandled rejections
process.on('unhandledRejection', (reason) => {
  console.error('Unhandled rejection:', reason);
  process.exit(1);
});

instanceof checks enable specific error handling per type. Unexpected errors should be re-thrown rather than silently swallowed.

Key points

Concepts covered

Custom Error, Error Subclass, instanceof, Error Types