> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cbrock.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Pipe & Flow

> Compose functions into readable pipelines.

`pipe` and `flow` let you chain multiple functions together without nested calls or intermediate variables. Both are fully type-safe: each function's return type determines the next function's input type, and TypeScript errors early if the types don't connect.

```typescript theme={null}
import { pipe, flow } from 'ts-chas/pipe';
```

## `pipe` — execute immediately

`pipe(initialValue, fn1, fn2, fn3)` passes `initialValue` through each function left-to-right and returns the final result:

```typescript theme={null}
const add5   = (x: number) => x + 5;
const double = (x: number) => x * 2;
const toStr  = (x: number) => `Result: ${x}`;

const result = pipe(10, add5, double, toStr);
// "Result: 30"
// Equivalent to: toStr(double(add5(10)))
```

Without `pipe`, the same code nests outward from the inside:

```typescript theme={null}
// Harder to read — you have to read inside-out
const result = toStr(double(add5(10)));
```

## `flow` — create a reusable function

`flow(fn1, fn2, fn3)` returns a new function that accepts the first function's input and returns the last function's output. Nothing runs until you call the result:

```typescript theme={null}
const transform = flow(add5, double, toStr);

transform(10); // "Result: 30"
transform(5);  // "Result: 20"
transform(0);  // "Result: 10"
```

<Tip>
  Use `pipe` when you have the value now. Use `flow` when you want to define the transformation once and apply it to multiple values later — for example, as a map callback or a reusable utility.
</Tip>

## Type safety

TypeScript checks each step in the pipeline. If the output type of one function doesn't match the input type of the next, you get a compile-time error:

```typescript theme={null}
const broken = pipe(
  'hello',
  (s: string) => s.length, // returns number
  (s: string) => s.trim()  // Error: Argument of type 'number' is not assignable to type 'string'
);
```

## The built-in `.pipe()` on Result

`Result<T, E>` and `ResultAsync<T, E>` have a `.pipe()` method that threads the full `Result` through a sequence of functions. Unlike the standalone `pipe`, these functions receive the `Result` itself, not just the inner value:

```typescript theme={null}
import { chas } from 'ts-chas';

const normalize = (r: chas.Result<string, string>) =>
  r.map((s) => s.trim().toLowerCase());

const validate = (r: chas.Result<string, string>) =>
  r.andThen((s) =>
    s.length > 0 ? chas.ok(s) : chas.err('Empty string')
  );

const result = chas.ok('  Hello World  ').pipe(normalize, validate);
// Ok('hello world')
```

This is useful for applying reusable Result transformations as a composable pipeline.

<Note>
  The `.pipe()` method on `Result` short-circuits on `Err` ; downstream functions still receive the `Result` and can choose to handle the error. It does not automatically skip errored steps the way `.map()` does. Build your pipeline functions to check `.isOk()` or use `.map()`, `.andThen()`, etc. internally.
</Note>

## Practical example

A data transformation pipeline that parses, validates, and formats an API payload:

```typescript theme={null}
import { pipe, flow } from 'ts-chas/pipe';
import { chas } from 'ts-chas';
import { is } from 'ts-chas/guard';

// Individual steps — small and testable
const parseId  = (raw: unknown) => is.string.uuid('v4').parse(raw);
const fetchUser = (id: string) => chas.fromPromise(
  fetch(`/api/users/${id}`).then((r) => r.json()),
  () => 'Fetch failed'
);
const formatName = (user: User) =>
  `${user.firstName} ${user.lastName}`.trim();

// Compose into a pipeline
const getUserName = flow(
  (rawId: unknown) => parseId(rawId),
  (result) => result.asyncAndThen(fetchUser),
  (task) => task.map(formatName)
);

const name = await getUserName(requestBody.userId);
// ResultAsync<string, GuardErr | string>
```
