Task<T, E> is a lazy, composable wrapper for async operations. Unlike a Promise, a Task does not start executing until you call .execute(). Every Task resolves to a Result<T, E>, giving you explicit, type-safe error handling throughout the chain.
Static factory methods
Task.from(fn, onError?)
Creates a Task from a function that returns a Promise. The optional onError mapper converts any thrown error into your typed E.
onError, the error type is unknown.
Task.ask<C>()
Creates a Task that resolves to the context value injected via .provide(). Use this to declare context dependencies without passing them explicitly through every function.
Task.go(generatorFn)
Do-notation for Tasks. Lets you write sequential async logic that looks imperative, while still short-circuiting on the first Err.
Task.void()
Returns a Task that resolves to Ok(undefined). Useful as a no-op or placeholder.
Task.fromOption(option, onNone)
Converts an Option<T> into a Task<T, E>. If the option is None, the task fails with the value returned by onNone.
Task.all(tasks)
Runs all tasks. Resolves to Ok with an array of all values if every task succeeds. Short-circuits to the first Err encountered.
Task.race(tasks)
Returns the result of whichever task settles first — success or failure.
Task.any(tasks)
Returns the first Ok. Only resolves to Err if all tasks fail, in which case the error is an array of all errors.
Task.collect(tasks)
Runs all tasks without short-circuiting. Resolves to Ok with all values if all succeed, or Err with all errors if any fail.
Task.parallel(tasks, concurrency)
Runs tasks with a bounded concurrency limit. Returns Ok with all values if all succeed, or the first Err.
Task.using(acquire, release, use)
Resource management helper. Acquires a resource, passes it to use, then calls release — even if use fails.
Instance methods
.chain(fn)
flatMap for Tasks. fn receives the Ok value and returns a new Task. Short-circuits on Err.
.map(fn)
Transforms the Ok value without changing the error type.
.mapErr(fn)
Transforms the Err value without changing the success type.
.tap(fn)
Runs a side effect on the Ok value. The result passes through unchanged.
.tapErr(fn)
Runs a side effect on the Err value. The result passes through unchanged.
.tapTag(target, handler)
Runs a side effect when the error matches a specific tagged error, without altering the result. Accepts either an error factory from defineErrs or a tag string.
.orElse(fn)
Recovery operator. If the Task fails, fn receives the error and returns a new Task to run instead.
.fallback(otherTask)
Semantic alias for .orElse(() => otherTask). Use when you always want to fall back to a fixed Task regardless of the error.
.catchTag(target, handler)
Catches a specific tagged error, handles it, and removes it from the error union type. The remaining union type is narrowed automatically.
.provide(context)
Injects a context value for Task.ask() chains. Call this before .execute().
Execution
.execute(signal?)
Runs the task and returns Promise<Result<T, E>>. Accepts an optional AbortSignal to cancel execution.
.unwrap()
Runs the task and returns Promise<T>. Throws if the result is Err. Use only when you’re certain the Task cannot fail.
Resilience
These operators let you build fault-tolerant tasks. See Resilience Patterns for full details and examples.| Method | Description |
|---|---|
.retry(count, options?) | Retry on failure, with optional exponential backoff |
.timeout(ms, onTimeout) | Fail if the task takes longer than ms milliseconds |
.circuitBreaker(options) | Open the circuit after too many consecutive failures |
.throttle(n) | Limit concurrent executions to n |
.delay(ms) | Wait ms milliseconds before executing |
.withSignal(signal) | Bind an AbortSignal; fail immediately if already aborted |
Caching
.once()
Executes the task once and caches the result forever. Subsequent calls return the cached Result without re-running.
.memoize(options?)
In-memory memoization with an optional TTL. By default, only successful results are cached.
| Option | Type | Description |
|---|---|---|
ttl | number | Cache lifetime in milliseconds. If omitted, caches forever. |
cacheErr | boolean | If true, errors are also cached. Default: false. |
.cache(key, store, options?)
External cache via any object that implements TaskCache. Useful for Redis, local storage, or shared application state.
Context
.context(ctx)
Attaches debug information to the error if the Task resolves to Err. The _context array on the error shows the most recent annotation first. Useful for tracing which step in a chain failed.
TaskCache interface
Implement this interface to use any storage backend with .cache().
Map satisfies this interface. For external stores, implement both methods: