Mastering TypeScript Error Handling with Custom Error Classes
Learn how to create and use custom error classes in TypeScript to write clearer and more robust error handling code.
Error handling is a crucial part of writing reliable applications. TypeScript enhances JavaScript by adding types, and you can leverage this to create custom error classes that make your error handling more structured and readable. In this article, you'll learn the basics of creating custom error classes in TypeScript and how to use them effectively.
By default, JavaScript has a built-in Error class that you can throw to represent an error. However, when you want to handle specific types of errors differently, creating your own error classes is the best practice.
class CustomError extends Error {
constructor(message: string) {
super(message);
this.name = 'CustomError';
Object.setPrototypeOf(this, CustomError.prototype);
}
}
// Usage example
try {
throw new CustomError('Something went wrong!');
} catch (error) {
if (error instanceof CustomError) {
console.log('Caught a custom error:', error.message);
} else {
console.log('Caught an unknown error');
}
}In this example, the `CustomError` class extends the built-in `Error` class. The `Object.setPrototypeOf` line is necessary in TypeScript to fix the prototype chain and ensure `instanceof` works correctly. When you throw a `CustomError`, you can specifically check for it in your error handling logic.
You can create as many custom error classes as you need for different error scenarios. This makes your errors more descriptive and helps organize your code better.
class ValidationError extends Error {
constructor(message: string) {
super(message);
this.name = 'ValidationError';
Object.setPrototypeOf(this, ValidationError.prototype);
}
}
class DatabaseError extends Error {
constructor(message: string) {
super(message);
this.name = 'DatabaseError';
Object.setPrototypeOf(this, DatabaseError.prototype);
}
}Now you can throw specific errors based on the situation, helping developers and users understand what went wrong exactly.
Finally, handling errors becomes cleaner as you can differentiate the type easily:
function processUserInput(input: string) {
if (!input) {
throw new ValidationError('Input cannot be empty');
}
// process input...
}
try {
processUserInput('');
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation error occurred:', error.message);
} else if (error instanceof DatabaseError) {
console.error('Database error:', error.message);
} else {
console.error('Unknown error:', error);
}
}In summary, mastering custom error classes in TypeScript allows you to build more understandable and maintainable error handling. Remember to always extend the built-in `Error` class and set the prototype correctly. This approach improves debugging and makes your application more robust.