Zero dependencies · TypeScript 5.5+

Fewer moving parts. Better async code.

Tuple-based errors, structured concurrency, and resource management for TypeScript — built on the primitives you already have.

Get startedAPI reference
typescript
import { safeTry } from "yieldless/error";
import { runTaskGroup } from "yieldless/task";

const [err, repo] = await safeTry(loadRepository(id));

if (err) {
  return [err, null] as const;
}

return await runTaskGroup(async (group) => {
  const refs   = group.spawn((s) => loadRefs(repo.path, s));
  const status = group.spawn((s) => loadStatus(repo.path, s));

  return { repo, refs: await refs, status: await status };
});

Design goals

What it optimizes for

Native control flow

Built on Promise, AbortController, AsyncLocalStorage, and Symbol.asyncDispose. No scheduler, no runtime, no magic.

Visible failure paths

If something can fail, the tuple is right there. No hidden exception channel unless you choose to rethrow.

Incremental adoption

Use one module at a time. No framework wrapper, no global runtime, no all-or-nothing commitment.


Modules

Pick what you need

Every module works independently. Import one, or compose several around the same [error, value] and AbortSignal conventions.

Plus result, resource, schedule, pubsub, singleflight, schema, node, and test.


27
Modules
0
Dependencies
TS 5.5+
Baseline

Ready to simplify?

Start with one module. Adopt more when they earn their place. Nothing wraps your application unless you ask it to.