Skip to content

Bridge Option: sync → Promise<Option>

Sync Option to Promise-of-Option lift operators.

Chains an async option-returning function over a sync IOption. Bridges from the sync Option world to the async world — unlike bind in async-option/ which works on AsyncOption.

Throw policy: a synchronous throw from fn converts to None; a rejected Promise from fn propagates as an outer rejection (promotion-family rule — the sync track stays rejection-free, and async failures are not swallowed).

export function bind<T, U>(
fn: (value: T) => Promise<IOption<U>> | IOption<U>,
): (opt: IOption<T>) => Promise<IOption<U>>;
export function bind<T, U>(
fn: (value: T) => Promise<IOption<U>> | IOption<U>,
opt: IOption<T>,
): Promise<IOption<U>>;

Defined in: bridge-option/bind.ts

import { bind } from '@sandlada/result/bridge-option';
import { match, ofSome, ofNone } from '@sandlada/result/option';
const input = ofSome(21);
const chained = await bind(async (x: number) => ofSome(x * 2), input);
const label = match((v) => `value:${v}`, () => 'nothing', chained);
// label === 'value:42'
const absent = ofNone<number>();
const skipped = await bind(async (x: number) => ofSome(x * 2), absent);
// skipped is None; bind short-circuits without invoking the callback

Lifts a sync IOption<T> into Promise<IOption<U>> via an async mapper. Companion to ../bridge-result/map.ts | bridge-result map for the Result world.

export function map<A, B>(
f: (a: A) => Promise<B>,
): (o: IOption<A>) => Promise<IOption<B>>;
export function map<A, B>(
f: (a: A) => Promise<B>,
o: IOption<A>,
): Promise<IOption<B>>;

Defined in: bridge-option/map.ts

import { map } from '@sandlada/result/bridge-option';
import { match, ofSome, ofNone } from '@sandlada/result/option';
const input = ofSome(5);
const lifted = await map(async (x: number) => x * 2, input);
const label = match((v) => `value:${v}`, () => 'nothing', lifted);
// label === 'value:10'
const empty = ofNone<number>();
const skipped = await map(async (x: number) => x * 2, empty);
// skipped is None; map passes None through without calling the mapper

Async match for sync IOption<T>. Pattern-matches with async-allowed handlers.

export function match<T, U>(
handlers: { some: (value: T) => U | Promise<U>; none: () => U | Promise<U> },
): (o: IOption<T>) => Promise<U>;
export function match<T, U>(
handlers: { some: (value: T) => U | Promise<U>; none: () => U | Promise<U> },
o: IOption<T>,
): Promise<U>;

Defined in: bridge-option/match.ts

import { match as bridgeMatch, map } from '@sandlada/result/bridge-option';
import { ofSome, ofNone } from '@sandlada/result/option';
const input = ofSome(21);
const scaled = await map(async (x: number) => x * 2, input);
const label = await bridgeMatch(
{ some: async (v: number) => `value:${v}`, none: async () => 'nothing' },
scaled,
);
// label === 'value:42'
const empty = ofNone<number>();
const message = await bridgeMatch(
{ some: async (v: number) => `value:${v}`, none: async () => 'nothing' },
empty,
);
// message === 'nothing'

Lifts a sync IOption<T> into Promise<IOption<T>> and recovers from None via an async callback.

Throw policy: a synchronous throw from f converts to None; a rejected Promise from f propagates as an outer rejection (promotion-family rule).

export function orElse<T>(
f: () => Promise<IOption<T>> | IOption<T>,
): (o: IOption<T>) => Promise<IOption<T>>;
export function orElse<T>(
f: () => Promise<IOption<T>> | IOption<T>,
o: IOption<T>,
): Promise<IOption<T>>;

Defined in: bridge-option/orElse.ts

import { orElse } from '@sandlada/result/bridge-option';
import { match, ofSome, ofNone } from '@sandlada/result/option';
const empty = ofNone<number>();
const recovered = await orElse(async () => ofSome(0), empty);
const label = match((v) => `value:${v}`, () => 'nothing', recovered);
// label === 'value:0'
const present = ofSome(42);
const untouched = await orElse(async () => ofSome(0), present);
// untouched stays Some(42); orElse short-circuits on Some
const same = match((v) => v, () => 0, untouched);
// same === 42

Side-effect on success for a sync IOption using an async callback.

Side-effect only. A synchronous throw from the callback converts to None (side-effect dropped); a rejected Promise propagates as an outer rejection (promotion-family rule, matches bind).

export function tap<T>(
fn: (a: T) => Promise<void | unknown>,
): (opt: IOption<T>) => Promise<IOption<T>>;
export function tap<T>(
fn: (a: T) => Promise<void | unknown>,
opt: IOption<T>,
): Promise<IOption<T>>;

Defined in: bridge-option/tap.ts

import { tap } from '@sandlada/result/bridge-option';
import { match, ofSome, ofNone } from '@sandlada/result/option';
const input = ofSome(42);
const touched = await tap(async (x: number) => { void x; }, input);
const label = match((v) => `still:${v}`, () => 'nothing', touched);
// label === 'still:42'; tap returns the original Some unchanged
const absent = ofNone<number>();
const passthrough = await tap(async (x: number) => { void x; }, absent);
// passthrough is None; tap short-circuits without running the callback