npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@praha/error-factory

v1.4.0

Published

A simple utility for creating custom errors effortlessly

Readme

@praha/error-factory

npm version npm download license Github

🤔 Why Use Custom Error Classes?

Using custom error classes provides several benefits:

  • Consistent Error Handling: Ensures a unified error structure across your application.
  • Better Debugging: Enables adding additional context such as error causes, metadata, and structured messages.
  • Improved Type Safety: When using TypeScript, custom error classes allow better type checking and inference.
  • Code Maintainability: Reduces redundant error-handling code and keeps error logic modular and reusable.

👏 Getting Started

Installation

npm install @praha/error-factory

Usage

You can use ErrorFactory to create custom error classes easily, reducing boilerplate code and ensuring consistent error structures across your application.

The following demonstrates the most basic usage of ErrorFactory to define and use a custom error class.

import { ErrorFactory } from '@praha/error-factory';

// Define a custom error
class NotFoundError extends ErrorFactory({
  name: 'NotFoundError',
  message: 'Resource not found',
}) {}

// Use the custom error
try {
  throw new NotFoundError();
} catch (error) {
  console.error(error.name); // "NotFoundError"
  console.error(error.message); // "Resource not found"
}

You can pass additional options to the error constructor, such as cause, which is useful for debugging complex error chains by preserving the original error context.

class DatabaseError extends ErrorFactory({
  name: 'DatabaseError',
  message: 'A database error occurred',
}) {}

try {
  throw new DatabaseError({ cause: new Error('Connection failed') });
} catch (error) {
  console.error(error.name); // "DatabaseError"
  console.error(error.message); // "A database error occurred"
  console.error(error.cause); // Error: Connection failed
}

Advanced Usage: Omitting the name

You can omit the name option. In that case, new.target.name (i.e. the class name) is automatically used at runtime.

class NotFoundError extends ErrorFactory({
  message: 'Resource not found',
}) {}

try {
  throw new NotFoundError();
} catch (error) {
  console.error(error.name); // "NotFoundError"
}

[!NOTE] When name is omitted, the type of name is inferred as string rather than a string literal type. This means type narrowing via the name property (e.g. switch (error.name)) is not available. If you need type narrowing, specify name explicitly or use instanceof instead.

Advanced Usage: Additional Fields

You can define additional fields directly in the ErrorFactory configuration, providing a more streamlined approach to adding custom properties without extending the class.

// Define an error with custom fields
class QueryError extends ErrorFactory({
  name: 'QueryError',
  message: 'An error occurred while executing a query',
  fields: ErrorFactory.fields<{ query: string; }>(),
}) {}

try {
  throw new QueryError({
    query: 'SELECT * FROM users',
    cause: new Error('Syntax error'),
  });
} catch (error) {
  console.error(error.name); // "QueryError"
  console.error(error.message); // "An error occurred while executing a query"
  console.error(error.query); // "SELECT * FROM users"
  console.error(error.cause); // Error: Syntax error
}

Advanced Usage: Dynamic Message Generation

You can define the message as a function that receives the custom fields as parameters, allowing for dynamic and contextual error messages based on the provided data.

// Define an error with dynamic message generation
class ValidationError extends ErrorFactory({
  name: 'ValidationError',
  message: ({ field, value }) => `Validation failed for field '${field}' with value '${value}'`,
  fields: ErrorFactory.fields<{ field: string; value: unknown; }>(),
}) {}

try {
  throw new ValidationError({
    field: 'email',
    value: 'invalid-email',
  });
} catch (error) {
  console.error(error.name); // "ValidationError"
  console.error(error.message); // "Validation failed for field 'email' with value 'invalid-email'"
}

This approach is particularly useful when you need error messages that include specific details about what went wrong, making debugging and error reporting more informative.

Advanced Usage: Type Narrowing with Unions

You can define multiple custom error classes and use TypeScript's type narrowing to handle them effectively based on their name property.

class NotFoundError extends ErrorFactory({
  name: 'NotFoundError',
  message: 'Resource not found',
}) {}

class ValidationError extends ErrorFactory({
  name: 'ValidationError',
  message: 'Invalid input',
}) {}

class DatabaseError extends ErrorFactory({
  name: 'DatabaseError',
  message: 'A database error occurred',
}) {}

type ApplicationError = NotFoundError | ValidationError | DatabaseError;

const handleError = (error: ApplicationError) => {
  switch (error.name) {
    case 'NotFoundError':
      console.error(`Handle not found: ${error.message}`);
      break;
    case 'ValidationError':
      console.error(`Handle validation error: ${error.message}`);
      break;
    case 'DatabaseError':
      console.error(`Handle database error: ${error.message}`);
      break;
  }
};

try {
  throw new ValidationError();
} catch (error) {
  if (error instanceof Error) {
    handleError(error as ApplicationError);
  }
}

Built-in Presets

@praha/error-factory provides built-in error classes for common use cases. These presets are ready to use out of the box and follow the same patterns as custom errors created with ErrorFactory.

UnexpectedError

A general-purpose error for handling unexpected situations in your application.

import { UnexpectedError } from '@praha/error-factory/presets';

try {
  throw new UnexpectedError();
} catch (error) {
  console.error(error.name); // "UnexpectedError"
  console.error(error.message); // "An unexpected error has occurred"
}

// You can also pass a cause
try {
  throw new UnexpectedError({ cause: new Error('Original error') });
} catch (error) {
  console.error(error.cause); // Error: Original error
}
UnreachableError

An error for marking code paths that should never be reached. This is particularly useful with TypeScript's exhaustive type checking.

import { UnreachableError } from '@praha/error-factory/presets';

type Status = 'pending' | 'success' | 'error';

const handleStatus = (status: Status) => {
  switch (status) {
    case 'pending':
      return 'Processing...';
    case 'success':
      return 'Completed';
    case 'error':
      return 'Failed';
    default:
      // TypeScript ensures all cases are handled
      throw new UnreachableError();
  }
};

🤝 Contributing

Contributions, issues and feature requests are welcome.

Feel free to check issues page if you want to contribute.

📝 License

Copyright © PrAha, Inc.

This project is MIT licensed.