In TypeScript, you can “bubble up” errors or exceptions from one method to another by allowing exceptions to propagate through the call stack. Here’s how you can achieve this with examples:
1. Basic Propagation of Errors
In TypeScript, you can throw errors from one method and catch them in a higher-level method, or let them propagate up to the top-level caller if they are not caught. Here’s a simple example demonstrating this:
class Example {
method1() {
try {
this.method2();
} catch (error) {
console.error('Error caught in method1:', error);
// You can choose to handle the error here or rethrow it
}
}
method2() {
// This will throw an error
throw new Error('Something went wrong in method2');
}
}
const example = new Example();
example.method1();
In this example, method2
throws an error that method1
catches. You can choose to handle the error in method1
or let it propagate further if method1
does not catch it.
2. Rethrowing Errors
If you catch an error in one method but want to let it bubble up to a higher level, you can rethrow it using throw
:
class Example {
method1() {
try {
this.method2();
} catch (error) {
console.error('Error caught in method1, rethrowing...');
throw error; // Rethrow the error to let it propagate
}
}
method2() {
// This will throw an error
throw new Error('Something went wrong in method2');
}
}
const example = new Example();
try {
example.method1();
} catch (error) {
console.error('Error caught in the outer scope:', error);
}
In this example, the error thrown in method2
is caught and rethrown by method1
, and then caught in the outer try...catch
block where method1
is called.
3. Custom Error Types
You can define custom error types for more specific error handling. Here’s how you can use custom errors to provide more context:
class CustomError extends Error {
constructor(message: string) {
super(message);
this.name = 'CustomError';
}
}
class Example {
method1() {
try {
this.method2();
} catch (error) {
if (error instanceof CustomError) {
console.error('CustomError caught in method1:', error);
} else {
console.error('General error caught in method1:', error);
}
throw error; // Rethrow the error to let it propagate
}
}
method2() {
// This will throw a CustomError
throw new CustomError('Something went wrong in method2');
}
}
const example = new Example();
try {
example.method1();
} catch (error) {
console.error('Error caught in the outer scope:', error);
}
4. Async Methods
For asynchronous methods, you should use async
/await
syntax, and you can propagate errors in a similar fashion:
class Example {
async method1() {
try {
await this.method2();
} catch (error) {
console.error('Error caught in method1:', error);
throw error; // Rethrow the error to let it propagate
}
}
async method2() {
// This will throw an error
throw new Error('Something went wrong in method2');
}
}
const example = new Example();
example.method1().catch(error => {
console.error('Error caught in the outer scope:', error);
});
In this asynchronous example, method2
throws an error that method1
catches, handles, and rethrows. The catch
block outside of method1
handles any errors that bubble up.
Summary
- Throw errors: Use
throw
to throw exceptions from methods. - Catch and rethrow: Use
try...catch
to handle exceptions in one method and optionally rethrow them. - Custom errors: Define and use custom error types for more specific error handling.
- Async errors: Use
async
/await
for handling errors in asynchronous methods.
This approach ensures that errors can be properly managed and handled at different levels of your application.