Custom Error Objects in JavaScript
In JavaScript, the Error
object is used to represent runtime errors, providing properties like message
and name
that help describe the error. While JavaScript has built-in error types such as TypeError
, SyntaxError
, and ReferenceError
, sometimes you need to create custom error types to handle specific situations in your code. This can be done by creating custom error objects that extend the native Error
class. In this article, we’ll explore how to create and use custom error objects in JavaScript with examples.
1. Creating a Basic Custom Error
You can create a custom error by defining a new class that extends the built-in Error
class. This allows you to create errors with specific names and messages tailored to your needs.
Example: Creating a ValidationError
class.
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
// Usage
try {
throw new ValidationError("Invalid input data");
} catch (error) {
console.log(error.name); // Outputs: ValidationError
console.log(error.message); // Outputs: Invalid input data
}
In this example, we create a ValidationError
class that inherits from Error
. When thrown, it includes a custom name
and a message.
2. Adding Custom Properties to Custom Errors
Custom error classes can include additional properties to store extra information about the error. This is especially helpful for debugging and providing detailed error information.
Example: Adding a field
property to the ValidationError
class.
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
// Usage
try {
throw new ValidationError("Invalid input data", "email");
} catch (error) {
console.log(error.name); // Outputs: ValidationError
console.log(error.message); // Outputs: Invalid input data
console.log(error.field); // Outputs: email
}
In this example, we add a field
property to the ValidationError
class. This property provides more context about which field caused the validation error.
3. Creating Multiple Custom Error Types
In some cases, it is beneficial to create multiple custom error classes to handle different error scenarios. For example, you might have a ValidationError
for input validation and a DatabaseError
for database-related issues.
Example: Defining ValidationError
and DatabaseError
classes.
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
class DatabaseError extends Error {
constructor(message) {
super(message);
this.name = "DatabaseError";
}
}
// Usage
try {
throw new DatabaseError("Failed to connect to the database");
} catch (error) {
console.log(error.name); // Outputs: DatabaseError
console.log(error.message); // Outputs: Failed to connect to the database
}
In this example, we create two custom error classes: ValidationError
and DatabaseError
. Each class has a unique name
property, making it easy to differentiate between different error types.
4. Using Custom Errors in Functions
Custom errors are often thrown within functions to handle specific cases or invalid conditions. You can use try
and catch
blocks to manage these errors appropriately.
Example: Using ValidationError
in a function.
function validateUser(user) {
if (!user.name) {
throw new ValidationError("Name is required", "name");
}
if (user.age < 18) {
throw new ValidationError("User must be at least 18 years old", "age");
}
return "User is valid";
}
// Usage
try {
validateUser({ age: 16 });
} catch (error) {
console.log(error.name); // Outputs: ValidationError
console.log(error.message); // Outputs: User must be at least 18 years old
console.log(error.field); // Outputs: age
}
In this example, the validateUser
function throws a ValidationError
if a user’s name is missing or age is below 18. The catch
block can handle these errors and access the additional information provided by the field
property.
5. Checking for Custom Errors
When catching errors, you can check if the error is an instance of a specific custom error class. This allows you to handle different error types separately.
Example: Checking for ValidationError
and DatabaseError
separately.
try {
throw new DatabaseError("Connection timed out");
} catch (error) {
if (error instanceof ValidationError) {
console.log("Validation error:", error.message);
} else if (error instanceof DatabaseError) {
console.log("Database error:", error.message);
} else {
console.log("General error:", error.message);
}
}
In this example, the catch
block uses instanceof
to determine the error type, allowing each type of error to be handled differently.
Conclusion
Creating custom error objects in JavaScript enables you to manage specific types of errors in a clear and organized way. By extending the Error
class, you can create error types with custom properties and handle each error scenario appropriately. Using custom error objects improves the readability of your code and enhances error handling, making your applications more robust and easier to debug.