DeesseJS Errors

Getting Started

Get started with @deessejs/errors, a TypeScript error handling library with exception chaining and hierarchical inheritance.

@deessejs/errors is a TypeScript library that reimagines error handling in JavaScript. Inspired by Python's exception system, it provides exception chaining, hierarchical inheritance, and rich error semantics through a function-based API.

This library is particularly useful when you need to:

  • Preserve the full context of errors across async boundaries and service calls
  • Organize errors in meaningful hierarchies that reflect your domain
  • Attach structured data and metadata to errors for better debugging

Quick Start

The quickest way to understand how @deessejs/errors works is to see it in action. Here's a basic example that demonstrates creating typed errors and chaining them together.

index.ts
import { error, raise } from '@deessejs/errors';
import { z } from 'zod';

// Define your error type. With a Standard Schema attached,
// every call validates the input and produces typed `fields`.
const ValidationError = error({
  name: 'ValidationError',
  fields: z.object({ field: z.string() }),
  message: (d) => `Validation failed for ${d.field}`,
});

// Use the factory to create error instances.
const validationErr = ValidationError({ field: 'email' });
console.log(validationErr.message); // "Validation failed for email"
console.log(validationErr.fields.field); // "email"

For catching and handling errors, you can use the standard try/catch syntax or the library's raise() function:

handling.ts
import { error, raise } from '@deessejs/errors';
import { z } from 'zod';

const ValidationError = error({
  name: 'ValidationError',
  fields: z.object({ field: z.string() }),
  message: (d) => `Validation failed for ${d.field}`,
});

try {
  raise(ValidationError({ field: 'email' }));
} catch (err) {
  // `err` is `unknown` in strict mode; narrow before reading.
  if (err instanceof Error) {
    console.log(err.name); // "ValidationError"
    console.log(err instanceof Error); // true
  }
}

Key Features

Exception Chaining

When an error occurs as a result of another error, you can preserve that relationship using the .from() method. This creates a chain that maintains the full history of what went wrong.

chaining.ts
import { causes, error } from '@deessejs/errors';
import { z } from 'zod';

const ValidationError = error({
  name: 'ValidationError',
  fields: z.object({ field: z.string() }),
  message: (d) => `Validation failed for ${d.field}`,
});

const AppError = error({ name: 'AppError' });

const validationErr = ValidationError({ field: 'email' });
const appErr = AppError();

// Chain the validation error as the cause.
appErr.from(validationErr);

console.log(appErr.cause === validationErr); // true
// The full chain is reachable via the causes() helper.
console.log(causes(appErr).length); // 1

Hierarchical Inheritance

Errors can inherit from other errors, creating hierarchies that are useful for organization and type checking. A child error can check against its parent types.

inheritance.ts
import { error, is } from '@deessejs/errors';

const AppError = error({ name: 'AppError' });
const ValidationError = error({
  name: 'ValidationError',
  inherits: AppError,
});

// The no-schema factories have an empty input shape; the
// call takes no arguments.
const err = ValidationError();

// Check the error type.
console.log(is(err, ValidationError)); // true
console.log(is(err, AppError)); // true (through inheritance)

Message Templates

You can define errors with function-form messages that read the schema's post-transform output. The message function receives the validated fields, so the rendered string is type-checked against the schema.

templates.ts
import { error } from '@deessejs/errors';
import { z } from 'zod';

const UserError = error({
  name: 'UserError',
  fields: z.object({
    userId: z.string(),
    reason: z.string(),
  }),
  message: (d) => `User "${d.userId}" failed: ${d.reason}`,
});

const err = UserError({ userId: 'usr_123', reason: 'not found' });
console.log(err.message); // 'User "usr_123" failed: not found'

See Also

On this page