Skip to main content
Tagged errors give you typed, discriminated Error instances that work naturally with Result, Task, and TypeScript’s type system. Each error has a _tag discriminant, extends the native Error class, and can be matched exhaustively — no more instanceof chains or untyped catch blocks.

chas.defineErrs(factories, baseProps?)

Defines a set of typed error factories. Each key becomes the _tag discriminant. The factory function returns extra properties that are merged onto the Error instance.
Each factory produces a real Error instance:
If the factory data includes a message or msg string, it becomes the error’s message. If it includes a cause that is an Error, it is set as Error.cause for native error wrapping.

baseProps

Pass a second argument to add shared properties to every error in the set:

Factory shortcuts

Each factory in the returned object also carries three shortcut methods:

.err()

Creates a Result.Err wrapping the error. Saves you from writing chas.err(AppError.NotFound(...)).

.errAsync()

Creates a ResultAsync.Err wrapping the error:

.is(value)

Type guard that checks whether an unknown value is this specific error:

Type inference

chas.InferErrs<typeof AppError>

Extracts the discriminated union of all error types from an error factory object.

chas.InferErr<typeof AppError.NotFound>

Extracts a single error variant’s type from a factory function.

chas.matchErr(error, handlers)

Exhaustively matches on a tagged error. TypeScript enforces that every _tag variant is handled — a compile error if you miss one.

chas.matchErrPartial(error, handlers)

Partial matching with a required _ wildcard fallback. Use when you only care about specific variants and want a catch-all for the rest.

.catchTag(target, handler) on Task / Result

Catches one specific tagged error from a Task or Result chain, handles it, and removes it from the error union type. The remaining error union is automatically narrowed. target can be a factory reference (AppError.NotFound) or a plain string ('NotFound').

.tapTag(target, handler) on Task / Result

Side-effect on a specific tagged error. The result passes through unchanged — the error is not caught.

Complete flow