Creating Error type
APIError factory creation
Overview
Extending globalThis.Error
have multiple drawbacks :
- Matching on errors relies on
instanceof
which have some limitations (ex:iframe
) - Can be verbose even for adding just one property
The @w5s/error
package helps creating type safe errors :
- Easy declaration extending
ErrorClass
- Type safe matching on
name
- Discourage matching using
instanceof
Declaring a new type
import { ErrorClass } from '@w5s/error';
// ┌─ ✓ PascalCase
// │ ✓ Name + 'Error'
// │ ┌─ Extends from ErrorClass()
export class {{SomeError}} extends ErrorClass({
errorName: '{{SomeError}}'; // <- Required
// errorMessage: 'This is an error message', // <- Optional
})<{
// ↓ Extra properties
// myProperty: string;
}> {}
Example 1 : Basic
import { ErrorClass } from '@w5s/error';
export class BasicError extends ErrorClass({
errorName: 'BasicError',
})<{}> {}
// Create an instance with :
//
// new BasicError();
// new BasicError({ message: 'Custom message' });
Example 2 : Advanced with extra properties
import { ErrorClass } from '@w5s/error';
export class AdvancedError extends ErrorClass({
errorName: 'AdvancedError',
errorMessage: 'Advanced error occurred',
})<{
customProperty: string;
}> {}
// Create an instance with :
//
// new AdvancedError({
// message: 'This is a message',
// customProperty: 'custom',
// cause: new TypeError('This is the cause')
// })
Matching errors
The recommended way to match on errors created with ErrorClass
is to use a switch
/ case
on the error name
class FooError extends ErrorClass({ errorName: 'FooError' })<{ fooProperty: string; }> {};
class BarError extends ErrorClass({ errorName: 'BarError' })<{ barProperty: number; }> {};
function parse(): Result<string, FooError | BarError> {
//...
}
function program() {
const result = parse();
if (Result.isError(result)) {
switch (result.name) {
case FooError.errorName: {
console.log('FooError:', error.fooProperty);
break;
}
case BarError.errorName: {
console.log('BarError:', error.barProperty);
break;
}
default: assertNever(result.name);
}
}
}
Caused / Specializing error
CustomError
can be used to create specific errors with a cause
property that is useful to keep track of the chain of errors.
class CauseError extends ErrorClass({ errorName: 'CauseError' })<{}> {};
try {
// ...
// return Result.Ok();
} catch (error) {
return Result.Error(new CauseError({
message: 'This is a better error',
cause: error, // <- The cause property can be any type but preferably an error object.
}));
}