Обзор

Map

Map successful behavior output.

composition

Install

$
Terminal window
pnpm dlx shadcn@latest add https://archyn.net/r/map.json

Copy the files below into the target paths shown in each tab.

ts@lib/flow/map.ts
import { type Awaitable } from "./core/result";
import { type Behavior, type RuntimeContext } from "./core/runtime";
import { pipe } from "./pipe";
import { task } from "./task";
/**
* Maps the successful output of a behavior.
*
* Source failures pass through unchanged. The projection can be synchronous or asynchronous, and
* thrown projection errors are captured by the underlying task runtime.
*
* @typeParam I - Source input type.
* @typeParam O - Source output type.
* @typeParam D - Projected output type.
* @typeParam E - Source domain error type.
* @typeParam C - Custom context type.
* @param source - Behavior whose success value should be transformed.
* @param project - Projection callback invoked only after source success.
* @returns A behavior with mapped output and the same domain error type.
*
* @example
* ```ts
* const loadName = map(loadUser, (user) => user.name);
* ```
*/
export function map<I, O, D, E, C extends object>(
source: Behavior<I, O, E, C>,
project: (output: O, context: RuntimeContext<C>) => Awaitable<D>,
): Behavior<I, D, E, C> {
return pipe(
source,
task<O, D, never, C>(async (output, taskContext) =>
taskContext.ok(await project(output, taskContext)),
),
);
}

Update the import paths to match your project setup.

Transform the successful output of a Behavior without changing its domain error type.

Usage

map projects successful values while leaving failures untouched. It is the Flow equivalent of mapping over an Ok value.

Use it when:

  • Normalize or shape successful output for the next step.
  • Keep the original domain error type.
  • Use async projection logic without writing a full task.
import { map } from "@/lib/flow/map";
import { task } from "@/lib/flow/task";
const loadUser = task((id: string) => fetch(`/api/users/${id}`).then((r) => r.json()));
const loadUserName = map(loadUser, (user: { name: string }) => user.name);

Behavior

map runs the source Behavior first. On success it calls project; on failure it returns the failure unchanged.

Domain failures from the source pass through unchanged. Projection exceptions are runtime Thrown errors through the underlying task/runtime path.

Types

Only the success output type changes; input, context, and domain error types stay the same.

Import from @/lib/flow/map.

Composition Notes

Use map for lightweight output shaping between larger workflow steps.

Do not use map for effects or failure handling; use tap, mapError, or recover.

Source

ts@lib/flow/map.ts
import { type Awaitable } from "./core/result";
import { type Behavior, type RuntimeContext } from "./core/runtime";
import { pipe } from "./pipe";
import { task } from "./task";
/**
* Maps the successful output of a behavior.
*
* Source failures pass through unchanged. The projection can be synchronous or asynchronous, and
* thrown projection errors are captured by the underlying task runtime.
*
* @typeParam I - Source input type.
* @typeParam O - Source output type.
* @typeParam D - Projected output type.
* @typeParam E - Source domain error type.
* @typeParam C - Custom context type.
* @param source - Behavior whose success value should be transformed.
* @param project - Projection callback invoked only after source success.
* @returns A behavior with mapped output and the same domain error type.
*
* @example
* ```ts
* const loadName = map(loadUser, (user) => user.name);
* ```
*/
export function map<I, O, D, E, C extends object>(
source: Behavior<I, O, E, C>,
project: (output: O, context: RuntimeContext<C>) => Awaitable<D>,
): Behavior<I, D, E, C> {
return pipe(
source,
task<O, D, never, C>(async (output, taskContext) =>
taskContext.ok(await project(output, taskContext)),
),
);
}