Promise Option operators
Eager operators on Promise of Option — barrel export.
Mirrors the structure of promise-result/ but for the Option type.
For lifting sync Option into Promise of Option, see ../bridge-option/index.js.
Functions
Section titled “Functions”bindAsync()
Section titled “bindAsync()”Chains an async option-returning function. fn can return IOption or Promise<IOption>.
Throw policy: if fn throws synchronously or its returned Promise rejects,
the result is None. The thrown reason is discarded.
export function bindAsync<T, U>( f: (a: T) => IOption<U> | Promise<IOption<U>>,): (r: Promise<IOption<T>>) => Promise<IOption<U>>;export function bindAsync<T, U>( f: (a: T) => IOption<U> | Promise<IOption<U>>, r: Promise<IOption<T>>,): Promise<IOption<U>>;Defined in: promise-option/bindAsync.ts
Example
Section titled “Example”import { bindAsync, unwrapOrAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const input = Promise.resolve(ofSome(21));const chained = bindAsync( (x: number) => (x > 0 ? Promise.resolve(ofSome(x * 2)) : Promise.resolve(ofNone())), input,);const value = await unwrapOrAsync(0, chained);// value === 42
const failed = Promise.resolve(ofNone<number>());const fallback = await unwrapOrAsync( 0, bindAsync((x: number) => Promise.resolve(ofSome(x)), failed),);// fallback === 0; bindAsync short-circuits on NonecontainsAsync()
Section titled “containsAsync()”Returns true if the Promise<IOption> is Some and contains the given value.
export function containsAsync<T>( value: T,): (r: Promise<IOption<T>>) => Promise<boolean>;export function containsAsync<T>( value: T, r: Promise<IOption<T>>,): Promise<boolean>;Defined in: promise-option/containsAsync.ts
Example
Section titled “Example”import { containsAsync, orElseAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const input = Promise.resolve(ofSome(42));const hasFortyTwo = await containsAsync(42, input);const backup = await orElseAsync( () => Promise.resolve(ofSome(0)), Promise.resolve(ofNone<number>()),);// hasFortyTwo === true// backup is Some(0); orElseAsync runs its fallback on None
const empty = Promise.resolve(ofNone<number>());const missing = await containsAsync(42, empty);// missing === false; containsAsync short-circuits on NoneexistsAsync()
Section titled “existsAsync()”Returns true if the Promise<IOption> is Some and the predicate holds.
Returns false on None or when the predicate does not hold.
Throw policy: If the predicate throws synchronously or returns a rejected
Promise, the error is caught and the result converts to false
(canonical catch+convert policy — see AGENTS.md).
export function existsAsync<T>( predicate: (a: T) => boolean | Promise<boolean>,): (r: Promise<IOption<T>>) => Promise<boolean>;export function existsAsync<T>( predicate: (a: T) => boolean | Promise<boolean>, r: Promise<IOption<T>>,): Promise<boolean>;Defined in: promise-option/existsAsync.ts
Example
Section titled “Example”import { existsAsync, filterAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const input = Promise.resolve(ofSome(42));const ok = await existsAsync(async (n) => n > 10, input);const narrowed = await filterAsync(async (n) => n > 10, input);// ok === true; narrowed resolves to Some(42)
const empty = Promise.resolve(ofNone<number>());const missing = await existsAsync(async (n) => n > 10, empty);// missing === false; existsAsync short-circuits on NonefilterAsync()
Section titled “filterAsync()”Filters the value of a Promise<IOption<T>> with a predicate.
Keeps the Some if the predicate holds; converts to None otherwise. None passes through.
Throw policy: If the predicate throws synchronously or returns a rejected
Promise, the error is caught and the result converts to None
(canonical catch+convert policy — see AGENTS.md).
export function filterAsync<T>( predicate: (a: T) => boolean | Promise<boolean>,): (r: Promise<IOption<T>>) => Promise<IOption<T>>;export function filterAsync<T>( predicate: (a: T) => boolean | Promise<boolean>, r: Promise<IOption<T>>,): Promise<IOption<T>>;Defined in: promise-option/filterAsync.ts
Example
Section titled “Example”import { filterAsync, unwrapOrAsync } from '@sandlada/result/promise-option';import { ofSome } from '@sandlada/result/option';
const input = Promise.resolve(ofSome(21));const kept = filterAsync(async (x: number) => x > 10, input);const value = await unwrapOrAsync(0, kept);// value === 21
const rejected = filterAsync(async (x: number) => x > 100, Promise.resolve(ofSome(21)));const fallback = await unwrapOrAsync(0, rejected);// fallback === 0 because filterAsync returned NoneflattenAsync()
Section titled “flattenAsync()”Flattens a nested Promise<IOption<IOption<T>>>.
Single-step only: unwraps exactly one layer. Call flattenAsync
repeatedly to flatten deeper nests.
export function flattenAsync<T>( r: Promise<IOption<IOption<T>>>,): Promise<IOption<T>>;Defined in: promise-option/flattenAsync.ts
Example
Section titled “Example”import { flattenAsync, matchAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const nested = Promise.resolve(ofSome(ofSome(42)));const flat = await flattenAsync(nested);const label = await matchAsync( (n) => String(n), () => 'empty', Promise.resolve(flat),);// label === '42'
const wrappedNone = Promise.resolve(ofSome(ofNone<number>()));const cleared = await flattenAsync(wrappedNone);const absent = await matchAsync( (n) => String(n), () => 'empty', Promise.resolve(cleared),);// absent === 'empty'; flattenAsync peeled Some off NonemapAsync()
Section titled “mapAsync()”Transforms the value of a Promise<IOption<T>>. The callback may be sync or async.
Throw policy: if f throws synchronously or its returned Promise rejects,
the result is None. The thrown reason is discarded.
export function mapAsync<T, U>( f: (a: T) => U | Promise<U>,): (r: Promise<IOption<T>>) => Promise<IOption<U>>;export function mapAsync<T, U>( f: (a: T) => U | Promise<U>, r: Promise<IOption<T>>,): Promise<IOption<U>>;Defined in: promise-option/mapAsync.ts
Example
Section titled “Example”import { mapAsync, matchAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const input = Promise.resolve(ofSome(5));const mapped = mapAsync((x: number) => x * 2, input);const label = await matchAsync( (n) => `value:${n}`, () => 'nothing', mapped,);// label === 'value:10'
const empty = Promise.resolve(ofNone<number>());const skipped = mapAsync((x: number) => x * 2, empty);const absent = await matchAsync( (n) => `value:${n}`, () => 'nothing', skipped,);// absent === 'nothing'; mapAsync passes None throughmapOrAsync()
Section titled “mapOrAsync()”Maps the value of Promise<IOption<T>>, returning a default on None.
Mirrors mapOrAsync for the Option-flavored pipeline.
export function mapOrAsync<A, B>( defaultValue: B, fn: (a: A) => B | Promise<B>,): (r: Promise<IOption<A>>) => Promise<B>;export function mapOrAsync<A, B>( defaultValue: B, fn: (a: A) => B | Promise<B>, r: Promise<IOption<A>>,): Promise<B>;Defined in: promise-option/mapOrAsync.ts
Example
Section titled “Example”import { mapAsync, mapOrAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const input = mapAsync((x: number) => x + 1, Promise.resolve(ofSome(20)));const total = await mapOrAsync(-1, (x: number) => x * 2, input);// total === 42
const missing = await mapOrAsync(-1, (x: number) => x * 2, Promise.resolve(ofNone()));// missing === -1; mapOrAsync uses the default on NonemapOrElseAsync()
Section titled “mapOrElseAsync()”Maps the value of Promise<IOption<T>>, or computes a default
from a thunk on None. Mirrors mapOrElseAsync for the Option-flavored pipeline.
export function mapOrElseAsync<A, B>( onNone: () => B | Promise<B>, fn: (a: A) => B | Promise<B>,): (r: Promise<IOption<A>>) => Promise<B>;export function mapOrElseAsync<A, B>( onNone: () => B | Promise<B>, fn: (a: A) => B | Promise<B>, r: Promise<IOption<A>>,): Promise<B>;Defined in: promise-option/mapOrElseAsync.ts
Example
Section titled “Example”import { mapAsync, mapOrElseAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const input = mapAsync((x: number) => x + 1, Promise.resolve(ofSome(20)));const total = await mapOrElseAsync(() => -1, (x: number) => x * 2, input);// total === 42
const missing = await mapOrElseAsync(() => -1, (x: number) => x * 2, Promise.resolve(ofNone()));// missing === -1; mapOrElseAsync calls onNone when the carrier is NonematchAsync()
Section titled “matchAsync()”Terminal — pattern-matches on both cases of an async option.
export function matchAsync<T, U>( onSome: (a: T) => U | Promise<U>, onNone: () => U | Promise<U>,): (r: Promise<IOption<T>>) => Promise<U>;export function matchAsync<T, U>( onSome: (a: T) => U | Promise<U>, onNone: () => U | Promise<U>, r: Promise<IOption<T>>,): Promise<U>;Defined in: promise-option/matchAsync.ts
Example
Section titled “Example”import { mapAsync, matchAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const input = Promise.resolve(ofSome(42));const doubled = mapAsync((n) => n * 2, input);const label = await matchAsync( (n) => `some: ${n}`, () => 'none', doubled,);// label === 'some: 84'
const empty = Promise.resolve(ofNone<number>());const absent = await matchAsync( (n) => `some: ${n}`, () => 'none', empty,);// absent === 'none'orElseAsync()
Section titled “orElseAsync()”Error recovery for async options.
Throw policy: if f throws synchronously or its returned Promise rejects,
the result is None. The thrown reason is discarded.
export function orElseAsync<T>( f: () => IOption<T> | Promise<IOption<T>>,): (r: Promise<IOption<T>>) => Promise<IOption<T>>;export function orElseAsync<T>( f: () => IOption<T> | Promise<IOption<T>>, r: Promise<IOption<T>>,): Promise<IOption<T>>;Defined in: promise-option/orElseAsync.ts
Example
Section titled “Example”import { orElseAsync, unwrapOrAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const recovered = orElseAsync( () => Promise.resolve(ofSome(42)), Promise.resolve(ofNone<number>()),);const value = await unwrapOrAsync(0, recovered);// value === 42
const kept = orElseAsync( () => Promise.resolve(ofSome(99)), Promise.resolve(ofSome(5)),);const same = await unwrapOrAsync(0, kept);// same === 5; orElseAsync leaves Some unchangedtapAsync()
Section titled “tapAsync()”Side-effect on the success track of an async option.
Throw policy: if fn throws synchronously or its returned Promise rejects,
the result is None. The thrown reason is discarded.
export function tapAsync<T>( fn: (a: T) => void | Promise<void>,): (r: Promise<IOption<T>>) => Promise<IOption<T>>;export function tapAsync<T>( fn: (a: T) => void | Promise<void>, r: Promise<IOption<T>>,): Promise<IOption<T>>;Defined in: promise-option/tapAsync.ts
Example
Section titled “Example”import { tapAsync, matchAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
let seen = 0;const input = Promise.resolve(ofSome(42));const touched = tapAsync(async (v: number) => { seen = v; }, input);const label = await matchAsync( (n) => String(n), () => 'none', touched,);// seen === 42 and label === '42'
const empty = tapAsync(async () => { seen = -1; }, Promise.resolve(ofNone<number>()));await matchAsync((n) => String(n), () => 'none', empty);// seen stays 42; tapAsync passes None through without invoking the side effecttapErrAsync()
Section titled “tapErrAsync()”Side-effect on both tracks of Promise<IOption<T>>.
Two callbacks: fn runs on the Some track (with the inner value), fnNone
runs on the None track - which is the failure track of an Option. Splitting
the callbacks eliminates the (value: T | undefined) lie - on None there is
genuinely no value, so the callback can’t pretend to receive one.
The Err in the name refers to the failure track of the Option, which is
None: fnNone is the observer for it. fn observes the Some track, the
same track tapAsyncOption observes.
Throw policy: a synchronous throw from either callback converts to
None; a rejected Promise propagates as an outer rejection
(promotion-family rule).
export function tapErrAsync<T>( fn: (value: T) => void | Promise<void>, fnNone?: () => void | Promise<void>,): (r: Promise<IOption<T>>) => Promise<IOption<T>>;export function tapErrAsync<T>( fn: (value: T) => void | Promise<void>, r: Promise<IOption<T>>, fnNone?: () => void | Promise<void>,): Promise<IOption<T>>;Defined in: promise-option/tapErrAsync.ts
Example
Section titled “Example”import { tapErrAsync, matchAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
let note = '';const present = tapErrAsync( (v: number) => { note = `some:${v}`; }, Promise.resolve(ofSome(7)),);const label = await matchAsync((n) => String(n), () => 'none', present);// note === 'some:7' and label === '7'
const absent = tapErrAsync( (_v: number) => { note = 'some'; }, Promise.resolve(ofNone<number>()), () => { note = 'none'; },);await matchAsync((n) => String(n), () => 'none', absent);// note === 'none'; fnNone runs on the None trackunwrapOrAsync()
Section titled “unwrapOrAsync()”Extracts the value on success from an async option, or returns a default on failure.
The default value type D is independent of the success type T, so a wider
or sentinel value can be supplied as a fallback — e.g.
unwrapOrAsync<number, null>(null) for a Promise<IOption<User>> resolves
to Promise<User | null>.
export function unwrapOrAsync<T = unknown, D = T>( defaultValue: D | Promise<D>,): <T2 extends T>(r: Promise<IOption<T2>>) => Promise<T2 | D>;export function unwrapOrAsync<T, D = T>( defaultValue: D | Promise<D>, r: Promise<IOption<T>>,): Promise<T | D>;Defined in: promise-option/unwrapOrAsync.ts
Example
Section titled “Example”import { mapAsync, unwrapOrAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const prepared = mapAsync((x: number) => x * 2, Promise.resolve(ofSome(21)));const value = await unwrapOrAsync(0, prepared);// value === 42
const empty = Promise.resolve(ofNone<number>());const fallback = await unwrapOrAsync(0, empty);// fallback === 0unwrapOrElseAsync()
Section titled “unwrapOrElseAsync()”Lazily extracts the value of Promise<IOption<T>>, computing a
default from a thunk on None. Returns Promise<T | D>. Mirrors
unwrapOrElseAsync for the Option-flavored pipeline.
The default value type D is independent of the success type T.
export function unwrapOrElseAsync<T = unknown, D = T>( onNone: () => D | Promise<D>,): <T2 extends T>(r: Promise<IOption<T2>>) => Promise<T2 | D>;export function unwrapOrElseAsync<T, D = T>( onNone: () => D | Promise<D>, r: Promise<IOption<T>>,): Promise<T | D>;Defined in: promise-option/unwrapOrElseAsync.ts
Example
Section titled “Example”import { mapAsync, unwrapOrElseAsync } from '@sandlada/result/promise-option';import { ofSome, ofNone } from '@sandlada/result/option';
const prepared = mapAsync((x: number) => x * 2, Promise.resolve(ofSome(21)));const value = await unwrapOrElseAsync(() => 0, prepared);// value === 42
const empty = Promise.resolve(ofNone<number>());const fallback = await unwrapOrElseAsync(() => 0, empty);// fallback === 0; unwrapOrElseAsync runs onNone when the carrier is None