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

@smbcheeky/error-object

v1.3.0

Published

Create errors that can be both thrown and returned. Make error handling easier for both JavaScript and TypeScript.

Readme

License deno.bundlejs.com npm downloads GitHub last commit GitHub stars

ErrorObject

A lightweight Error subclass for structured, chainable error handling in JavaScript and TypeScript. Errors that can be both thrown and returned with built-in type guards, chainable setters, and logging.

Installation

npm install @smbcheeky/error-object
yarn add @smbcheeky/error-object

Why ErrorObject?

ErrorObject extends Error, so it works everywhere a regular Error does (instanceof Error, try/catch, etc.) while adding structure and ergonomics:

  • Throw or return — use whichever pattern fits your codebase
  • Type guardsisErrorObject(), ErrorObject.is(), and instanceof all work for narrowing types
  • Structured propertiescode, message, numberCode, details, domain, tag, and raw
  • Chainable setters — modify any property inline with .setCode(), .setMessage(), etc.
  • Setters accept transforms — pass a function to access the current value while modifying it
  • Built-in logging.log(tag) and .debugLog(tag) for inline logging
  • Subclass-friendly — works correctly with extends ErrorObject

Quick Start

import { ErrorObject, isErrorObject, ResultObject, ErrorObjectParams } from "@smbcheeky/error-object";

// Create an error
const error = new ErrorObject({
  code: "auth/invalid-token",
  message: "Your session has expired.",
  domain: "auth",
});

// Chain setters and log inline
error
.setDetails("Please sign in again.")
.setNumberCode(401)
.debugLog("AUTH");

// [AUTH] Your session has expired. [auth/invalid-token]
// [DEBUG] { "code": "auth/invalid-token", "numberCode": 401, ... }

Creating Errors

// From explicit properties
new ErrorObject({ code: "not-found", message: "User not found." });

// Generic error (uses configurable defaults)
ErrorObject.generic();

// Generic error with a tag
ErrorObject.withTag("network-timeout");

// Clone an existing error
existingError.clone();
// .new() also works but is deprecated in favor of .clone()

Type Guards

All three approaches narrow the type correctly in TypeScript:

const result: { success: true } | ErrorObject = someFn();

// Option 1: standalone function
if (isErrorObject(result)) {
  result.code; // TypeScript knows this is ErrorObject
  return;
}

// Option 2: static method
if (ErrorObject.is(result)) {
  result.code;
  return;
}

// Option 3: instanceof
if (result instanceof ErrorObject) {
  result.code;
  return;
}

result; // TypeScript knows this is { success: true }

Chainable Setters

Every setter returns this, so you can chain them. Each setter accepts either a value or a transform function:

ErrorObject.generic()
.setCode("upload/too-large")
.setMessage("File exceeds the size limit.")
.setDomain("storage")
.setNumberCode(413)
.setDetails("Maximum file size is 10MB.")
.setTag("upload-validation")
.setRaw(originalError);

// Transform function — access the current value
error.setMessage((old) => `${old} Please try again.`);

Properties

| Property | Type | Required | Description | |--------------|----------|----------|------------------------------------------------------| | code | string | Yes | Identifier for the error, ideally human-readable | | message | string | Yes | Primary error message | | numberCode | number | No | Numeric code (e.g. HTTP status) | | details | string | No | Extended description, suitable for showing to users | | domain | string | No | Category grouping (e.g. "auth", "storage") | | tag | string | No | Finer-grained label for filtering or identification | | raw | any | No | Original error or payload used to create this object |

The constructor accepts an ErrorObjectParams object, which is exported for use in wrapper functions and utilities.

Logging

.log(tag) outputs toString(), .debugLog(tag) outputs toDebugString() which includes a full JSON dump:

new ErrorObject({ code: "timeout", message: "Request timed out.", domain: "api" })
.log("NET")
.debugLog("NET");

// [NET] Request timed out. [api/timeout]
// [NET] Request timed out. [api/timeout]
// [DEBUG] { "code": "timeout", "message": "Request timed out.", "domain": "api" }

Both methods return this so they can be chained inline.

Tag Checks

const error = ErrorObject.generic();

error.isGeneric();   // true — checks if tag matches GENERIC_TAG
error.hasTag();      // true — checks if any tag is set
error.hasTag("foo"); // false — checks for a specific tag

Serialization

.toJSON() returns a clean object with only ErrorObject properties (no inherited Error fields or internal discriminators):

const error = new ErrorObject({ code: "not-found", message: "User not found.", domain: "users" });
JSON.stringify(error);
// {"code":"not-found","message":"User not found.","domain":"users"}

String Output

.toString() produces a clean, user-facing string. .toDebugString() appends a full JSON dump prefixed with [DEBUG]. What .toString() includes is configurable:

ErrorObject.INCLUDE_CODE_IN_STRING = true;   // default
ErrorObject.INCLUDE_DOMAIN_IN_STRING = false; // default

new ErrorObject({ code: "not-found", message: "User not found.", domain: "users" }).toString();
// "User not found. [not-found]"

ErrorObject.INCLUDE_DOMAIN_IN_STRING = true;
// "User not found. [users/not-found]"

Static Configuration

Override these static properties to customize defaults across your app:

// Change the generic error defaults
ErrorObject.GENERIC_CODE = "error";
ErrorObject.GENERIC_MESSAGE = "An unexpected error occurred";
ErrorObject.GENERIC_TAG = "generic-error-object";

// Control what toString() includes
ErrorObject.INCLUDE_CODE_IN_STRING = true;
ErrorObject.INCLUDE_DOMAIN_IN_STRING = false;

// Replace the log method (default is console.log)
ErrorObject.LOG_METHOD = myLogger.error;

// Disable logging entirely
ErrorObject.LOG_METHOD = null;

Subclassing

ErrorObject is designed to be extended. instanceof checks work correctly for derived classes:

class ApiError extends ErrorObject {
}

const err = new ApiError({ code: "500", message: "Internal server error" });
err instanceof ApiError;     // true
err instanceof ErrorObject;  // true
err instanceof Error;        // true

ResultObject

ResultObject<T> wraps either a success value or an ErrorObject, giving you a type-safe way to return errors instead of throwing them:

import { ResultObject, ErrorObject } from "@smbcheeky/error-object";

function getUser(id: string): ResultObject<User> {
  if (!id) return ResultObject.err(new ErrorObject({ code: "invalid-id", message: "Missing ID" }));
  return ResultObject.ok({ name: "Alice" });
}

const result = getUser("123");

if (result.isOk()) {
  result.data;  // User — TypeScript narrows the type
}

if (result.isErr()) {
  result.error; // ErrorObject
}

Guards

All guards narrow the type correctly in TypeScript:

| Method | Narrows to | |--------------|------------------------------------------| | .isOk() | { data: T; error: undefined } | | .hasData() | same as .isOk() | | .isData() | same as .isOk() | | .isErr() | { data: undefined; error: ErrorObject } | | .isError() | same as .isErr() |

Parsing Errors from Any Payload

To create an ErrorObject from API responses, caught exceptions, or other unknown payloads, see @smbcheeky/error-object-from-payload.

More Examples

See the playground for runnable examples.