Skip to main content
Tagged errors are native Error instances extended with a _tag discriminant. They let you build discriminated unions of errors that TypeScript can check exhaustively — and that work with real stack traces, console.log, and error monitoring services.

Defining errors

chas.defineErrs() takes an object where each key becomes a _tag and the value is a factory function that returns the error’s extra data:
Each factory produces a real Error instance with:
  • A _tag field matching the key name
  • A name field set to the tag
  • A full stack trace
  • All the data properties you returned from the factory

Creating errors

Call the factory directly, or use the .err() helper to wrap it in a Result:

Inferring types

Using errors in function signatures

Exhaustive matching

chas.matchErr() requires a handler for every variant. TypeScript will error if you miss one:

Partial matching

chas.matchErrPartial() lets you handle only the variants you care about. The _ handler catches everything else and receives the remaining union type:

Catching a specific tag mid-chain

.catchTag() handles a single variant inline, removing it from the error union. The remaining chain has a narrower error type:
You can also match by tag string instead of factory:

Tapping a tag without catching

.tapTag() runs a side effect on a specific variant but leaves the result unchanged:

Guard integration

Use is.tagged() to check an unknown value against a tagged error factory:
Each error factory has a .is(value) method as a convenience type guard. You can also use is.tagged(AppError.NotFound) from ts-chas/guard for the same effect.

Error wrapping with cause

If your factory data includes a cause property that is an Error, it is set as the native Error.cause, creating a proper error chain: