Creating Your Own Error Types
In large projects, a generic Error isn't specific enough. Custom error classes let you distinguish between different failure modes and react to them appropriately.
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field; // Extra context: which field failed?
}
}
class NetworkError extends Error {
constructor(message, statusCode) {
super(message);
this.name = 'NetworkError';
this.statusCode = statusCode;
}
}
function validateUser(user) {
if (!user.name) throw new ValidationError('Name is required', 'name');
if (!user.email) throw new ValidationError('Email is required', 'email');
}
async function saveUser(user) {
try {
validateUser(user);
const response = await fetch('/api/users', { method: 'POST', body: JSON.stringify(user) });
if (!response.ok) throw new NetworkError('Server error', response.status);
} catch (err) {
if (err instanceof ValidationError) {
showFieldError(err.field, err.message); // Handle validation
} else if (err instanceof NetworkError) {
showNetworkError(err.statusCode); // Handle network
} else {
throw err; // Unknown — re-throw!
}
}
}
Note
Using instanceof lets you precisely identify the error type and respond differently to each kind.