Skip to content

[new tool] @agent-tools/result — Type-safe Result and Option types for error handling #215

@burner-agent

Description

@burner-agent

Tool Name

@agent-tools/result

Description

Type-safe Result<T, E> and Option<T> types for explicit error handling without exceptions, with chainable transformations, async support, and aggregation utilities.

Why It's Useful for Agents

AI agents execute multi-step pipelines where any step can fail — API calls, file reads, parsing, tool invocations. Untyped try/catch loses error type information and makes it impossible to reason about failure modes at compile time. Result types force explicit error handling at every boundary, preventing silent failures that cascade into incorrect agent outputs.

Primary research: neverthrow (7.5k stars, MIT, TypeScript 98.2%, v8.2.0 Feb 2025, ~1.6M weekly npm downloads) — provides Result<T, E> and ResultAsync<T, E> with map/andThen/match/combine. Also evaluated option-t (356 stars, MIT, v56.1.0 Apr 2026, ~146k weekly downloads, tree-shakable standalone functions, Nullable/Undefinable/Maybe + Result + Option), ts-results (~188k weekly downloads, lightweight Result/Option), and oxide.ts (585 stars, MIT, ~24k weekly downloads, Rust-faithful API — stale since 2022).

neverthrow leads in adoption but option-t's tree-shakable function-based design is superior for SDK packaging. This tool combines neverthrow's ergonomic API with option-t's tree-shakable architecture.

Proposed API

import { ok, err, some, none, Result, Option, ResultAsync } from "@agent-tools/result";

// Result creation
const success = ok<number, string>(42);
const failure = err<number, string>("not found");

// Chaining transformations
const result = ok(rawInput)
  .map(parse)
  .andThen(validate)    // returns Result
  .mapErr(normalizeError);

// Pattern matching
result.match({
  ok: (value) => console.log(value),
  err: (error) => console.error(error),
});

// Async pipelines
const asyncResult = ResultAsync.fromPromise(
  fetch(url),
  (e) => new NetworkError(e)
).andThen((res) => parseJson(res));

// Aggregation
const combined = Result.combine([r1, r2, r3]); // Result<[T1, T2, T3], E>
const allErrors = Result.combineWithAllErrors([r1, r2, r3]);

// Option type
const opt: Option<User> = some(user);
opt.map(u => u.name).unwrapOr("anonymous");

// Wrapping throwable functions
const safeParse = Result.fromThrowable(JSON.parse, (e) => new ParseError(e));
const parsed = safeParse(untrustedInput); // Result<unknown, ParseError>

// Collecting results from iterables
const results = await ResultAsync.collect(urls.map(fetchSafely));

Scope

In scope:

  • Result<T, E> with ok/err constructors and chainable methods (map, mapErr, andThen, orElse, match, unwrapOr)
  • ResultAsync<T, E> wrapping Promise with identical method surface
  • Option<T> with some/none constructors and map/andThen/unwrapOr/toResult
  • fromThrowable / fromPromise / fromAsyncThrowable exception capture wrappers
  • combine / combineWithAllErrors for aggregating multiple Results
  • Tree-shakable function exports alongside method-chain API
  • ESLint rule or TypeScript utility to detect unchecked Results

Out of scope:

  • Full functional programming toolkit (use Effect or fp-ts)
  • Monad transformers, higher-kinded types, or category theory abstractions
  • Runtime error tracking or reporting (see observability tools)
  • Retry logic or circuit breakers (see @agent-tools/resilience)

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is neededinfrastructureCI, workflows, build toolingnew-toolProposal for a new tool packagetier:autonomyTier 3 — self-extension, shell, orchestrationtier:utilityTier 1 — standalone utility packages

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions