Use Result.do
Deep andThen chains get unreadable fast. Result.do lets you yield* each step and read the pipeline top-to-bottom.
Synchronous
import { Result } from "antithrow";
const pipeline = Result.do(function* () {
const contents = yield* readFile(path);
const parsed = yield* parseJson(contents);
const validated = yield* validate(parsed);
return validated;
});
Each yield* on a Result unwraps an Ok to its value and short-circuits on Err — the surrounding pipeline is a Result<T, E> whose E is the union of every error the generator yields.
Asynchronous
If any yield* is a Pending or Promise, Result.do returns a Pending:
const response = await Result.do(async function* () {
const raw = yield* Result.fromPromise(fetch("/api"));
const parsed = yield* Result.fromPromise(raw.json());
return parsed;
});
Use an async function* generator when awaiting is required. Plain generators are fine for sync-only flows.
When Result.do beats andThen
- More than two or three steps.
- Steps with different error types (the union is cleaner than nested
mapErr). - Reusing intermediate values across multiple downstream calls.
andThen is fine when every step flows into exactly the next one.
See also
- Reference:
Result.do - How-to: Combine results