The pipeable module provides modern functional programming utilities for chainable operations using the pipe function and pipeable operator style. This is the recommended modern approach for using fp-ts, offering better type inference and composition than traditional method chaining.
import { pipe } from "fp-ts/lib/pipeable";
import { pipeable } from "fp-ts/lib/pipeable";The fundamental composition function that enables left-to-right function application, replacing nested function calls with readable pipelines.
/**
* Pipe function for left-to-right function composition
* Supports up to 10 function compositions with full type safety
*/
function pipe<A>(a: A): A;
function pipe<A, B>(a: A, ab: (a: A) => B): B;
function pipe<A, B, C>(a: A, ab: (a: A) => B, bc: (b: B) => C): C;
function pipe<A, B, C, D>(a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D;
// ... continues up to 10 parametersUsage Examples:
import { pipe } from "fp-ts/lib/pipeable";
import { map, filter, fold } from "fp-ts/lib/Array";
import { some, none, fold as optionFold } from "fp-ts/lib/Option";
// Array processing pipeline
const result = pipe(
[1, 2, 3, 4, 5],
filter((n: number) => n > 2),
map((n: number) => n * 2),
fold(0, (acc: number, n: number) => acc + n)
);
// Result: 18
// Option processing pipeline
const maybeDouble = pipe(
some(21),
map((n: number) => n * 2),
optionFold(
() => "No value",
(value: number) => `Value: ${value}`
)
);
// Result: "Value: 42"Type-safe interfaces that provide pipeable versions of common functional operations for all data types that support them.
interface PipeableFunctor<F> {
readonly map: <A, B>(f: (a: A) => B) => (fa: HKT<F, A>) => HKT<F, B>;
}
interface PipeableFunctor1<F extends URIS> {
readonly map: <A, B>(f: (a: A) => B) => (fa: Kind<F, A>) => Kind<F, B>;
}
interface PipeableFunctor2<F extends URIS2> {
readonly map: <A, B>(f: (a: A) => B) => <L>(fa: Kind2<F, L, A>) => Kind2<F, L, B>;
}interface PipeableApply<F> extends PipeableFunctor<F> {
readonly ap: <A>(fa: HKT<F, A>) => <B>(fab: HKT<F, (a: A) => B>) => HKT<F, B>;
readonly apFirst: <B>(fb: HKT<F, B>) => <A>(fa: HKT<F, A>) => HKT<F, A>;
readonly apSecond: <B>(fb: HKT<F, B>) => <A>(fa: HKT<F, A>) => HKT<F, B>;
}interface PipeableChain<F> extends PipeableApply<F> {
readonly chain: <A, B>(f: (a: A) => HKT<F, B>) => (ma: HKT<F, A>) => HKT<F, B>;
readonly chainFirst: <A, B>(f: (a: A) => HKT<F, B>) => (ma: HKT<F, A>) => HKT<F, A>;
readonly flatten: <A>(mma: HKT<F, HKT<F, A>>) => HKT<F, A>;
}interface PipeableFoldable<F> {
readonly reduce: <A, B>(b: B, f: (b: B, a: A) => B) => (fa: HKT<F, A>) => B;
readonly foldMap: <M>(M: Monoid<M>) => <A>(f: (a: A) => M) => (fa: HKT<F, A>) => M;
readonly reduceRight: <A, B>(b: B, f: (a: A, b: B) => B) => (fa: HKT<F, A>) => B;
}interface PipeableFilterable<F> extends PipeableCompactable<F> {
readonly filter: {
<A, B extends A>(refinement: Refinement<A, B>): (fa: HKT<F, A>) => HKT<F, B>;
<A>(predicate: Predicate<A>): (fa: HKT<F, A>) => HKT<F, A>;
};
readonly filterMap: <A, B>(f: (a: A) => Option<B>) => (fa: HKT<F, A>) => HKT<F, B>;
readonly partition: {
<A, B extends A>(refinement: Refinement<A, B>): (fa: HKT<F, A>) => Separated<HKT<F, A>, HKT<F, B>>;
<A>(predicate: Predicate<A>): (fa: HKT<F, A>) => Separated<HKT<F, A>, HKT<F, A>>;
};
readonly partitionMap: <A, RL, RR>(
f: (a: A) => Either<RL, RR>
) => (fa: HKT<F, A>) => Separated<HKT<F, RL>, HKT<F, RR>>;
}Creates pipeable operators from type class instances, enabling the modern functional style for any data type.
/**
* Creates pipeable operators from a type class instance
* Automatically detects available operations and generates appropriate pipeable functions
*/
function pipeable<F extends URIS4, I>(
I: { URI: F } & I
): PipeableChain4<F> & PipeableApply4<F> & PipeableFunctor4<F> & /* ... other interfaces based on I */;
function pipeable<F extends URIS3, I>(
I: { URI: F } & I
): PipeableChain3<F> & PipeableApply3<F> & PipeableFunctor3<F> & /* ... other interfaces based on I */;
function pipeable<F extends URIS2, I>(
I: { URI: F } & I
): PipeableChain2<F> & PipeableApply2<F> & PipeableFunctor2<F> & /* ... other interfaces based on I */;
function pipeable<F extends URIS, I>(
I: { URI: F } & I
): PipeableChain1<F> & PipeableApply1<F> & PipeableFunctor1<F> & /* ... other interfaces based on I */;Usage Examples:
import { pipeable } from "fp-ts/lib/pipeable";
import { option } from "fp-ts/lib/Option";
import { either } from "fp-ts/lib/Either";
import { array } from "fp-ts/lib/Array";
// Create pipeable operators for Option
const { map, chain, filter } = pipeable(option);
// Create pipeable operators for Either
const { map: mapE, mapLeft, bimap } = pipeable(either);
// Create pipeable operators for Array
const { map: mapA, filter: filterA, fold } = pipeable(array);
// Use in pipelines
pipe(
some(42),
map((n: number) => n * 2),
chain((n: number) => n > 50 ? some(n) : none),
filter((n: number) => n % 2 === 0)
);interface PipeableBifunctor<F> {
readonly bimap: <L, A, M, B>(f: (l: L) => M, g: (a: A) => B) => (fa: HKT2<F, L, A>) => HKT2<F, M, B>;
readonly mapLeft: <L, M>(f: (l: L) => M) => <A>(fa: HKT2<F, L, A>) => HKT2<F, M, A>;
}interface PipeableContravariant<F> {
readonly contramap: <A, B>(f: (b: B) => A) => (fa: HKT<F, A>) => HKT<F, B>;
}interface PipeableMonadThrow<F> {
readonly fromOption: <E>(onNone: () => E) => <A>(ma: Option<A>) => HKT<F, A>;
readonly fromEither: <E, A>(ma: Either<E, A>) => HKT<F, A>;
readonly fromPredicate: {
<E, A, B extends A>(refinement: Refinement<A, B>, onFalse: (a: A) => E): (a: A) => HKT<F, B>;
<E, A>(predicate: Predicate<A>, onFalse: (a: A) => E): (a: A) => HKT<F, A>;
};
readonly filterOrElse: {
<E, A, B extends A>(refinement: Refinement<A, B>, onFalse: (a: A) => E): (ma: HKT<F, A>) => HKT<F, B>;
<E, A>(predicate: Predicate<A>, onFalse: (a: A) => E): (ma: HKT<F, A>) => HKT<F, A>;
};
}All pipeable interfaces come in multiple variants to support fp-ts's Higher Kinded Types system:
// For HKT (generic)
interface PipeableFunctor<F> { /* ... */ }
// For URIS (single type parameter)
interface PipeableFunctor1<F extends URIS> { /* ... */ }
// For URIS2 (two type parameters)
interface PipeableFunctor2<F extends URIS2> { /* ... */ }
// For URIS2C (two type parameters, first constrained)
interface PipeableFunctor2C<F extends URIS2, L> { /* ... */ }
// For URIS3 (three type parameters)
interface PipeableFunctor3<F extends URIS3> { /* ... */ }
// For URIS4 (four type parameters)
interface PipeableFunctor4<F extends URIS4> { /* ... */ }import { pipe } from "fp-ts/lib/pipeable";
import { some, none, map, chain, fold } from "fp-ts/lib/Option";
const processValue = (input: number) => pipe(
some(input),
map((n: number) => n * 2),
chain((n: number) => n > 10 ? some(n) : none),
fold(
() => "Value too small",
(n: number) => `Processed value: ${n}`
)
);import { pipe } from "fp-ts/lib/pipeable";
import { left, right, map, mapLeft, fold } from "fp-ts/lib/Either";
const parseAndDouble = (input: string) => pipe(
parseInt(input, 10),
(n: number) => isNaN(n) ? left("Invalid number") : right(n),
map((n: number) => n * 2),
mapLeft((error: string) => `Parse error: ${error}`),
fold(
(error: string) => ({ success: false, error }),
(value: number) => ({ success: true, value })
)
);import { pipe } from "fp-ts/lib/pipeable";
import { map, filter, fold } from "fp-ts/lib/Array";
const processNumbers = (numbers: number[]) => pipe(
numbers,
filter((n: number) => n > 0),
map((n: number) => n * n),
fold(0, (acc: number, n: number) => acc + n)
);// Higher Kinded Types support
import { HKT, HKT2, Kind, Kind2, Kind3, Kind4, URIS, URIS2, URIS3, URIS4 } from './HKT';
// Supporting types
import { Predicate, Refinement } from './function';
import { Option } from './Option';
import { Either } from './Either';
import { Separated } from './Compactable';
import { Monoid } from './Monoid';