Skip to content

Op

Op: object

Defined in: Core/Op.ts:114

interpret: <Args, E, A, O>(op, options) => InterpretResult<Args, E, A, O> = interpretFn

Interprets an Op blueprint with a concurrency and lifecycle strategy, returning a Manager.

Args extends readonly unknown[]

E

A

O extends AllInterpretOptions<Args, E>

Op<Args, E, A>

O

InterpretResult<Args, E, A, O>

Op.make to construct an Op blueprint.

const manager = Op.interpret(fetchUser, { strategy: "restartable" });

is: object

idle: <E, A>(state) => state is Idle = isIdle

Type guard that checks if an Op state is Idle.

E = unknown

A = unknown

State<E, A>

state is Idle

  • Op.is.pending to check if an Op is actively executing.
  • Op.is.settled to check if an Op has completed execution.
if (Op.is.idle(manager.state)) {
  console.log("Ready to execute");
}

pending: <E, A>(state) => state is Pending = isPending

Type guard that checks if an Op state is Pending (actively executing).

E = unknown

A = unknown

State<E, A>

state is Pending

  • Op.is.idle to check if an Op is waiting to execute.
  • Op.is.settled to check if an Op has completed execution.
if (Op.is.pending(manager.state)) {
  showSpinner();
}

queued: <E, A>(state) => state is Queued = isQueued

Type guard that checks if an Op state is Queued (waiting in a concurrency queue).

E = unknown

A = unknown

State<E, A>

state is Queued

Op.is.pending to check if an Op is actively executing.

if (Op.is.queued(manager.state)) {
  console.log("Position in queue:", manager.state.position);
}

retrying: <E, A>(state) => state is Retrying<E> = isRetrying

Type guard that checks if an Op state is Retrying after a failure.

E

A

State<E, A>

state is Retrying<E>

Op.is.pending to check if an Op is actively executing.

if (Op.is.retrying(manager.state)) {
  console.log("Retry attempt:", manager.state.attempt);
}

settled: <E, A>(state) => state is Outcome<E, A> = isSettled

Type guard that checks if an Op state has settled into an outcome (Ok, Err, or Nil).

E

A

State<E, A>

state is Outcome<E, A>

  • Op.is.pending to check if an Op is actively executing.
  • Op.is.idle to check if an Op has not yet run.
if (Op.is.settled(manager.state)) {
  console.log("Operation completed with outcome:", manager.state.kind);
}

lift: {<Fn>(factory, options?): Op<Parameters<Fn>, unknown, Awaited<ReturnType<Fn>>>; <Input, Out>(factory, options?): Op<NormalizeArgs<Input>, unknown, Awaited<Out>>; <Args, Out>(factory, options?): Op<Args, unknown, Awaited<Out>>; } = liftFn

Lifts an async action into an Op blueprint without requiring explicit error transformation. Unknown errors thrown by the async action are passed through untyped.

Arguments to the returned function can be inferred automatically or provided as explicit generics:

  • Op.lift((signal) => (opts: Payload) => ...) (inferred)
  • Op.lift<Payload, User>((signal) => (opts) => ...) (explicit input/output)
  • Op.lift<typeof apiFn>((signal) => apiFn) (explicit function signature)

<Fn>(factory, options?): Op<Parameters<Fn>, unknown, Awaited<ReturnType<Fn>>>

Fn extends (…args) => unknown

(signal) => Fn

string

Op<Parameters<Fn>, unknown, Awaited<ReturnType<Fn>>>

<Input, Out>(factory, options?): Op<NormalizeArgs<Input>, unknown, Awaited<Out>>

Input

Out

(signal) => (…args) => Out | PromiseLike<Out>

string

Op<NormalizeArgs<Input>, unknown, Awaited<Out>>

<Args, Out>(factory, options?): Op<Args, unknown, Awaited<Out>>

Args extends readonly unknown[]

Out

(signal) => (…args) => Out | PromiseLike<Out>

string

Op<Args, unknown, Awaited<Out>>

Op.make to construct an Op with a typed error transformation.

const fetchOp = Op.lift((signal) => (url: string) => fetch(url, { signal }));

make: {<Fn, E>(factory, options): Op<Parameters<Fn>, E, Awaited<ReturnType<Fn>>>; <Input, Out, E>(factory, options): Op<NormalizeArgs<Input>, E, Awaited<Out>>; <Args, Out, E>(factory, options): Op<Args, E, Awaited<Out>>; } = makeFn

Creates an Op blueprint from a signal-accepting factory function that returns the async action, along with an error mapping handler.

Arguments to the returned function can be inferred automatically or provided as explicit generics:

  • Op.make((signal) => (opts: Payload) => ...) (inferred)
  • Op.make<Payload, User>((signal) => (opts) => ...) (explicit input/output)
  • Op.make<typeof apiFn>((signal) => apiFn) (explicit function signature)

<Fn, E>(factory, options): Op<Parameters<Fn>, E, Awaited<ReturnType<Fn>>>

Fn extends (…args) => unknown

E = unknown

(signal) => Fn

string

(error) => E

Op<Parameters<Fn>, E, Awaited<ReturnType<Fn>>>

<Input, Out, E>(factory, options): Op<NormalizeArgs<Input>, E, Awaited<Out>>

Input

Out

E = unknown

(signal) => (…args) => Out | PromiseLike<Out>

string

(error) => E

Op<NormalizeArgs<Input>, E, Awaited<Out>>

<Args, Out, E>(factory, options): Op<Args, E, Awaited<Out>>

Args extends readonly unknown[]

Out

E = unknown

(signal) => (…args) => Out | PromiseLike<Out>

string

(error) => E

Op<Args, E, Awaited<Out>>

Op.lift to construct an Op without explicit error transformation.

const fetchUser = Op.make(
  (signal) => (id: string) => fetch(`/users/${id}`, { signal }).then(r => r.json() as Promise<User>),
  { onError: (error) => new ApiError(error) },
);

Outcome: object = OpOutcome

Settled outcome value constructors, type guards, eliminators, and combinators.

chain: <A, B, E2>(transform) => <E1>(outcome) => Outcome<E2 | E1, B>

Sequences an operation that produces an Op.Outcome if the current outcome is Ok.

A

B

E2 = never

(value) => Outcome<E2, B>

<E1>(outcome) => Outcome<E2 | E1, B>

Op.Outcome.map to transform the inner value without returning a new Op.Outcome.

pipe(outcome, Op.Outcome.chain((val) => validate(val)));

from: object

Maybe: <A>(maybe, onNone?) => Outcome<never, A>

Creates an Op.Outcome from a Maybe, mapping Some to OpOk and None to OpNil.

A

Maybe<A>

The Maybe to convert.

() => NilReason

Optional callback returning the cancellation or drop reason (defaults to “dropped”).

Outcome<never, A>

Op.Outcome.to.Maybe to convert an outcome to a Maybe.

const outcome = Op.Outcome.from.Maybe(Maybe.make.some(42));
// { kind: "OpOk", value: 42 }

const dropped = Op.Outcome.from.Maybe(Maybe.make.none(), () => "aborted");
// { kind: "OpNil", reason: "aborted" }

Result: <E, A>(result) => Outcome<E, A>

Creates an Op.Outcome from a Result, mapping Ok to OpOk and Err to OpErr.

E

A

Result<E, A>

Outcome<E, A>

Op.Outcome.to.Result to convert an outcome to a Result.

const outcome = Op.Outcome.from.Result(Result.make.ok(42));
// { kind: "OpOk", value: 42 }

getOrElse: <B>(fallback) => <E, A>(outcome) => B | A

Returns the value if Ok, otherwise executes the fallback function and returns its result.

B

() => B

<E, A>(outcome) => B | A

pipe(outcome, Op.Outcome.getOrElse(() => defaultValue));

is: object

err: <E, A>(stateOrOutcome) => stateOrOutcome is Err<E> = isErr

Type guard that checks if an Op state or outcome is Err.

E

A

State<E, A>

stateOrOutcome is Err<E>

  • Op.Outcome.is.ok to check if an outcome or state is Ok.
  • Op.Outcome.is.nil to check if an outcome or state is Nil.
if (Op.Outcome.is.err(outcome)) {
  showError(outcome.error);
}

nil: <E, A>(stateOrOutcome) => stateOrOutcome is Nil = isNil

Type guard that checks if an Op state or outcome is Nil.

E

A

State<E, A>

stateOrOutcome is Nil

  • Op.Outcome.is.ok to check if an outcome or state is Ok.
  • Op.Outcome.is.err to check if an outcome or state is Err.
if (Op.Outcome.is.nil(outcome)) {
  console.log("Skipped due to:", outcome.reason);
}

ok: <E, A>(stateOrOutcome) => stateOrOutcome is Ok<A> = isOk

Type guard that checks if an Op state or outcome is Ok.

E

A

State<E, A>

stateOrOutcome is Ok<A>

  • Op.Outcome.is.err to check if an outcome or state is Err.
  • Op.Outcome.is.nil to check if an outcome or state is Nil.
if (Op.Outcome.is.ok(outcome)) {
  render(outcome.value);
}

make: object

err: <E>(error) => Err<E> = makeErr

Creates an Err outcome with the given error.

E

E

Err<E>

  • Op.Outcome.make.ok to create an Ok outcome.
  • Op.Outcome.make.nil to create a Nil outcome.
Op.Outcome.make.err("Something went wrong"); // { kind: "OpErr", error: "Something went wrong" }

nil: (reason) => Nil = makeNil

Creates a Nil outcome with the given cancellation or drop reason.

NilReason

Nil

  • Op.Outcome.make.ok to create an Ok outcome.
  • Op.Outcome.make.err to create an Err outcome.
Op.Outcome.make.nil("aborted"); // { kind: "OpNil", reason: "aborted" }

ok: <A>(value) => Ok<A> = makeOk

Creates an Ok outcome with the given value.

A

A

Ok<A>

  • Op.Outcome.make.err to create an Err outcome.
  • Op.Outcome.make.nil to create a Nil outcome.
Op.Outcome.make.ok(42); // { kind: "OpOk", value: 42 }

map: <A, B>(transform) => <E>(outcome) => Outcome<E, B>

Transforms the value inside an Ok outcome using the provided function.

A

B

(value) => B

<E>(outcome) => Outcome<E, B>

  • Op.Outcome.chain to sequence operations that themselves return an Op.Outcome.
  • Op.Outcome.mapError to transform the error inside an Err outcome.
pipe(outcome, Op.Outcome.map((x) => x * 2));

mapError: <E, F>(transform) => <A>(outcome) => Outcome<F, A>

Transforms the error inside an Err outcome using the provided function.

E

F

(error) => F

<A>(outcome) => Outcome<F, A>

Op.Outcome.map to transform the value inside an Ok outcome.

pipe(outcome, Op.Outcome.mapError((err) => new CustomError(err)));

match: <E, A, B>(cases) => (outcome) => B

Matches on an Op outcome by providing handlers for each variant.

E

A

B

(error) => B

(reason) => B

(value) => B

(outcome) => B

pipe(
  outcome,
  Op.Outcome.match({
    ok: (value) => `Value: ${value}`,
    err: (error) => `Error: ${error}`,
    nil: (reason) => `Cancelled: ${reason}`,
  }),
);

recover: <E1, B, E2>(handler) => <A>(outcome) => Outcome<E2, B | A>

Recovers from an Err outcome by applying a recovery function that returns a new Op.Outcome.

E1

B

E2 = never

(error) => Outcome<E2, B>

<A>(outcome) => Outcome<E2, B | A>

pipe(outcome, Op.Outcome.recover((err) => Op.Outcome.make.ok(fallbackValue)));

tap: <A>(sideEffect) => <E>(outcome) => Outcome<E, A>

Executes a side effect if the outcome is Ok and returns the original outcome unchanged.

A

(value) => void

<E>(outcome) => Outcome<E, A>

Op.Outcome.tapError to execute a side effect on Err outcomes.

pipe(outcome, Op.Outcome.tap((val) => console.log(val)));

tapError: <E>(sideEffect) => <A>(outcome) => Outcome<E, A>

Executes a side effect if the outcome is Err and returns the original outcome unchanged.

E

(error) => void

<A>(outcome) => Outcome<E, A>

Op.Outcome.tap to execute a side effect on Ok outcomes.

pipe(outcome, Op.Outcome.tapError((err) => console.error(err)));

to: object

Maybe: <E, A>(outcome) => Maybe<A>

Converts an Op.Outcome to a Maybe, mapping Ok to Some and both Err and Nil to None.

E = never

A = never

Outcome<E, A>

Maybe<A>

  • Op.Outcome.to.Result to convert an outcome to a Result.
  • Op.Outcome.from.Maybe to create an outcome from a Maybe.
pipe(outcome, Op.Outcome.to.Maybe);

Result: <E2>(onNil) => <E1, A>(outcome) => Result<E2 | E1, A>

Converts an Op.Outcome to a Result.

E2

(reason) => E2

<E1, A>(outcome) => Result<E2 | E1, A>

  • Op.Outcome.to.Maybe to convert an outcome to a Maybe.
  • Op.Outcome.from.Result to create an outcome from a Result.
pipe(outcome, Op.Outcome.to.Result((reason) => new Error(`Skipped: ${reason}`)));

wire: <Args, E, A, S>(source, sideEffect) => () => void

Subscribes to an Op manager and executes a side-effect whenever the manager emits an Ok outcome. Returns an unsubscribe callback.

Args extends readonly unknown[]

E

A

S extends State<E, A>

Manager<Args, E, A, S>

(value) => void

() => void

const unsubscribe = Op.wire(userManager, (user) => analyticsManager.run(user.id));