Skip to main content

Overview

better-result provides robust error handling through:
  • TaggedError - Factory for creating discriminated error classes
  • Exhaustive matching - Type-safe error handling with matchError()
  • UnhandledException - Wrapper for unexpected exceptions
  • Panic - Unrecoverable errors (defects in user code)

TaggedError Factory

Creating Tagged Errors

TaggedError is a factory function that creates error classes with a _tag discriminator for exhaustive type checking.

Why TaggedError?

TaggedError provides several benefits over plain Error objects:
The _tag property enables exhaustive pattern matching:
TypeScript enforces that all error variants are handled.
Store domain-specific information:
TaggedError automatically chains Error causes in stack traces:
TaggedError instances serialize cleanly:

Type Signature

Exhaustive Error Matching

matchError()

Exhaustively pattern match on a union of tagged errors. TypeScript enforces that all variants are handled.
If you remove a handler, TypeScript will produce a compile error. This ensures all error cases are handled.

Data-Last (Pipeable) API

matchErrorPartial()

Partial pattern match with a fallback for unhandled errors.

Type Narrowing in Fallback

The fallback parameter is typed as Exclude<E, HandledErrors>, providing type safety:

Error Recovery Patterns

Mapping Errors to Default Values

Converting Errors to Success

Retrying on Specific Errors

UnhandledException

UnhandledException wraps exceptions caught by Result.try() and Result.tryPromise() when no custom catch handler is provided.

When to Use UnhandledException

When you want quick error wrapping without defining custom error types:

Panic: Unrecoverable Errors

Panic represents defects in user code - situations where recovery is impossible:
  • Callback throws inside map(), andThen(), match(), etc.
  • catch handler throws in Result.try() or Result.tryPromise()
  • finally block throws in Result.gen()
  • Generator body throws before yielding
  • Symbol.dispose or Symbol.asyncDispose throws

Why Panic?

Unlike recoverable errors (wrapped in Err), Panics indicate programming errors that shouldn’t be caught and handled - they should be fixed.

Panic in Generators

Panics should never be caught and ignored. They indicate bugs in your code that need to be fixed.

Avoiding Panics

Type Guards

TaggedError.is()

Every TaggedError class has a static is() type guard:

isTaggedError()

Check if a value is any TaggedError instance:

isPanic()

Check if a value is a Panic:

Best Practices

Create discriminated error unions for your domain:
Prefer matchError() over if-else chains:
Let Panics crash the application - they indicate bugs:
Store enough information to debug issues:

Next Steps

Pattern Matching

Learn how to handle Results with match() and type narrowing

Generator Composition

Master Result.gen() for imperative-style error handling