Skip to main content

Creating Error type

Error factory creation

API

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.
}));
}

FAQ