Skip to main content

Overview

Result.gen() enables imperative-style error handling using JavaScript generators and yield* syntax:
  • Write code that looks synchronous but short-circuits on first error
  • Automatic error type union inference across multiple yields
  • Support for finally blocks, using declarations, and async operations
  • Type-safe alternative to try-catch and promise chaining

Basic Usage

Simple Composition

Short-Circuiting on Error

When any yield* encounters an Err, execution stops immediately:
This is railway-oriented programming: operations proceed on the “success track” until an error switches to the “error track”.

How It Works

The yield* Operator

yield* delegates to the iterator protocol. Ok and Err implement [Symbol.iterator]:
When Result.gen() encounters a yielded Err, it stops the generator and returns that error.

Type Inference

TypeScript infers the union of all yielded error types:

Comparison to Other Patterns

vs Try-Catch

vs Promise Chaining

vs andThen Chaining

Use andThen() for simple linear chains. Use Result.gen() when you need:
  • Multiple intermediate values
  • Conditional logic
  • Loops or complex control flow
  • Resource cleanup with finally

Async Generators

Result.await()

Wrap Promise<Result> to make it yieldable in async generators:

Mixing Sync and Async

Error Propagation

Automatic Error Union

Errors from all yields are automatically unioned:

Normalizing Error Types

Use mapError() to convert error unions to a single type:

Resource Cleanup

Finally Blocks

finally blocks run even when short-circuiting:
If a finally block throws, Result.gen() will throw a Panic. Ensure cleanup code doesn’t throw:

Using Declarations (Resource Management)

TC39 Explicit Resource Management (Stage 3) works with Result.gen():

Async Resource Management

Complex Control Flow

Conditional Logic

Loops

If any yield* in the loop fails, the entire operation stops and returns that error.

Early Returns

Context Binding

Bind this context with the second parameter:

Real-World Examples

User Registration Flow

Batch Processing with Rollback

Multi-Step Workflow

Best Practices

The generator body must return Result.ok() or Result.err():
Throwing before any yield* will cause a Panic:
Wrap cleanup in try-catch:
Always wrap Promise<Result> with Result.await():

Summary

Use Result.gen() when you need:
  • Imperative style - Code that reads like normal sync/async code
  • Multiple values - Access to intermediate results
  • Complex control flow - Conditions, loops, early returns
  • Resource cleanup - finally blocks or using declarations
  • Error union - Automatic inference of all possible error types
Avoid Result.gen() when:
  • Simple linear transformations (use map()/andThen())
  • Purely functional composition (use pipeable API)
  • No intermediate values needed

Next Steps

Creating Results

Learn how to create Result instances with ok, err, try, and tryPromise

Error Handling

Master TaggedError and exhaustive error matching