Skip to content

Function

Provides small helpers for defining and reusing TypeScript functions.

The main helpers are pipe and flow for left-to-right composition and dual for APIs that support both direct and pipe-friendly call styles. The module also contains small identity, constant, tuple, type-level, and memoization helpers used across the library.

24 exports Added in v2.0.0 Source

Caching

memoize

Added in v4.0.0 Source

Creates a memoized function whose input is an object, caching results by object identity.

When to use

Use to reuse the result of a synchronous computation whose output is stable for a given object reference.

Details

Each memoized wrapper owns a private WeakMap keyed by object identity.

Gotchas

undefined is reserved to represent a cache miss and is therefore not supported as a return value.

Structurally equal objects do not share cache entries. If the same object is mutated after its first call, later calls still return the cached result for that reference.

Signature

declare function memoize<A extends object, O extends {} | null>(f: (a: A) => O): (ast: A) => O;

Combinators

apply

Added in v2.0.0 Source

Applies a function to a given value.

When to use

Use to pass a fixed value into a unary function, especially when the function is the value flowing through pipe.

Details

apply(a)(f) is equivalent to f(a).

See

  • pipe for building left-to-right pipelines

Signature

declare function apply<A>(a: A): <B>(self: (a: A) => B) => B;

compose

Added in v2.0.0 Source

Composes two functions, ab and bc into a single function that takes in an argument a of type A and returns a result of type C. The result is obtained by first applying the ab function to a and then applying the bc function to the result of ab.

When to use

Use to compose exactly two unary functions into a reusable unary function.

See

  • flow for composing a left-to-right sequence of functions
  • pipe for applying a value through a left-to-right sequence immediately

Signature

declare const compose: {
  <B, C>(bc: (b: B) => C): <A>(self: (a: A) => B) => (a: A) => C;
  <A, B, C>(self: (a: A) => B, bc: (b: B) => C): (a: A) => C;
};

dual

Added in v2.0.0 Source

Creates a function that can be called in data-first style or data-last (pipe-friendly) style.

When to use

Use to expose one implementation through both direct and pipe-friendly call styles.

Details

Pass either the arity of the uncurried function or a predicate that decides whether the current call is data-first. Arity is the common case. Use a predicate when optional arguments make arity ambiguous.

Signature

declare const dual: {
  <DataLast extends (...args: Array<any>) => any, DataFirst extends (...args: Array<any>) => any>(
    arity: Parameters<DataFirst>["length"],
    body: DataFirst,
  ): DataLast & DataFirst;
  <DataLast extends (...args: Array<any>) => any, DataFirst extends (...args: Array<any>) => any>(
    isDataFirst: (args: IArguments) => boolean,
    body: DataFirst,
  ): DataLast & DataFirst;
};

flip

Added in v2.0.0 Source

Reverses the order of arguments for a curried function.

When to use

Use to adapt a curried function when its argument groups need to be supplied in the opposite order.

Signature

declare function flip<A extends Array<unknown>, B extends Array<unknown>, C>(
  f: (...a: A) => (...b: B) => C,
): (...b: B) => (...a: A) => C;

flow

Added in v2.0.0 Source

Performs left-to-right function composition.

When to use

Use to build a reusable function from a left-to-right sequence of transformations.

Details

The first function may have any arity. Every following function must be unary.

See

  • pipe for applying a value through a left-to-right sequence immediately
  • compose for composing exactly two functions

Signature

declare function flow<A extends readonly Array<unknown>, B = never>(ab: (...a: A) => B): (...a: A) => B
declare function flow<A extends readonly Array<unknown>, B = never, C = never>(ab: (...a: A) => B, bc: (b: B) => C): (...a: A) => C
declare function flow<A extends readonly Array<unknown>, B = never, C = never, D = never>(ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...a: A) => D
declare function flow<A extends readonly Array<unknown>, B = never, C = never, D = never, E = never>(ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E): (...a: A) => E
declare function flow<A extends readonly Array<unknown>, B = never, C = never, D = never, E = never, F = never>(ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F): (...a: A) => F
declare function flow<A extends readonly Array<unknown>, B = never, C = never, D = never, E = never, F = never, G = never>(ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G): (...a: A) => G
declare function flow<A extends readonly Array<unknown>, B = never, C = never, D = never, E = never, F = never, G = never, H = never>(ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H): (...a: A) => H
declare function flow<A extends readonly Array<unknown>, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never>(ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I): (...a: A) => I
declare function flow<A extends readonly Array<unknown>, B = never, C = never, D = never, E = never, F = never, G = never, H = never, I = never, J = never>(ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J): (...a: A) => J

identity

Added in v2.0.0 Source

Returns its input argument unchanged.

When to use

Use to return a value unchanged where a function is required.

Signature

declare function identity<A>(a: A): A;

pipe

Added in v2.0.0 Source

Pipes the value of an expression through a left-to-right sequence of functions.

When to use

Use when you need to compose data-last functions into readable transformation pipelines instead of method-style chains.

Details

Takes an initial value, passes it to the first function, then passes each result to the next function in order. The final function result is returned.

Gotchas

Each function passed after the initial value must accept a single argument, because pipe calls each step with only the previous result.

Signature

declare function pipe<A>(a: A): A;
declare function pipe<A, B = never>(a: A, ab: (a: A) => B): B;
declare function pipe<A, B = never, C = never>(a: A, ab: (a: A) => B, bc: (b: B) => C): C;
declare function pipe<A, B = never, C = never, D = never>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
): D;
declare function pipe<A, B = never, C = never, D = never, E = never>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
): E;
declare function pipe<A, B = never, C = never, D = never, E = never, F = never>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
): F;
declare function pipe<A, B = never, C = never, D = never, E = never, F = never, G = never>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
): G;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
): H;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
): I;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
): J;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
): K;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
  L = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
  kl: (k: K) => L,
): L;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
  L = never,
  M = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
  kl: (k: K) => L,
  lm: (l: L) => M,
): M;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
  L = never,
  M = never,
  N = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
  kl: (k: K) => L,
  lm: (l: L) => M,
  mn: (m: M) => N,
): N;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
  L = never,
  M = never,
  N = never,
  O = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
  kl: (k: K) => L,
  lm: (l: L) => M,
  mn: (m: M) => N,
  no: (n: N) => O,
): O;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
  L = never,
  M = never,
  N = never,
  O = never,
  P = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
  kl: (k: K) => L,
  lm: (l: L) => M,
  mn: (m: M) => N,
  no: (n: N) => O,
  op: (o: O) => P,
): P;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
  L = never,
  M = never,
  N = never,
  O = never,
  P = never,
  Q = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
  kl: (k: K) => L,
  lm: (l: L) => M,
  mn: (m: M) => N,
  no: (n: N) => O,
  op: (o: O) => P,
  pq: (p: P) => Q,
): Q;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
  L = never,
  M = never,
  N = never,
  O = never,
  P = never,
  Q = never,
  R = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
  kl: (k: K) => L,
  lm: (l: L) => M,
  mn: (m: M) => N,
  no: (n: N) => O,
  op: (o: O) => P,
  pq: (p: P) => Q,
  qr: (q: Q) => R,
): R;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
  L = never,
  M = never,
  N = never,
  O = never,
  P = never,
  Q = never,
  R = never,
  S = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
  kl: (k: K) => L,
  lm: (l: L) => M,
  mn: (m: M) => N,
  no: (n: N) => O,
  op: (o: O) => P,
  pq: (p: P) => Q,
  qr: (q: Q) => R,
  rs: (r: R) => S,
): S;
declare function pipe<
  A,
  B = never,
  C = never,
  D = never,
  E = never,
  F = never,
  G = never,
  H = never,
  I = never,
  J = never,
  K = never,
  L = never,
  M = never,
  N = never,
  O = never,
  P = never,
  Q = never,
  R = never,
  S = never,
  T = never,
>(
  a: A,
  ab: (a: A) => B,
  bc: (b: B) => C,
  cd: (c: C) => D,
  de: (d: D) => E,
  ef: (e: E) => F,
  fg: (f: F) => G,
  gh: (g: G) => H,
  hi: (h: H) => I,
  ij: (i: I) => J,
  jk: (j: J) => K,
  kl: (k: K) => L,
  lm: (l: L) => M,
  mn: (m: M) => N,
  no: (n: N) => O,
  op: (o: O) => P,
  pq: (p: P) => Q,
  qr: (q: Q) => R,
  rs: (r: R) => S,
  st: (s: S) => T,
): T;

SK

Added in v2.0.0 Source

Returns the second argument and discards the first. The SK combinator is a fundamental combinator in the lambda calculus and the SKI combinator calculus.

When to use

Use to discard the first argument and return the second argument.

Signature

declare function SK<A, B>(_: A, b: B): B;

tupled

Added in v2.0.0 Source

Creates a tupled version of this function: instead of n arguments, it accepts a single tuple argument.

When to use

Use to adapt a multi-argument function so it accepts one tuple argument.

See

  • untupled for adapting a tuple-argument function back to multiple arguments

Signature

declare function tupled<A extends readonly Array<unknown>, B>(f: (...a: A) => B): (a: A) => B

untupled

Added in v2.0.0 Source

Converts a tupled function back to an uncurried function.

When to use

Use to adapt a tuple-argument function so it accepts multiple arguments.

See

  • tupled for adapting a multi-argument function to one tuple argument

Signature

declare function untupled<A extends readonly Array<unknown>, B>(f: (a: A) => B): (...a: A) => B

Constants

constFalse

Added in v2.0.0 Source

Returns false when called.

When to use

Use when you need a thunk that returns false on every invocation.

Signature

declare const constFalse: LazyArg<boolean>;

constNull

Added in v2.0.0 Source

Returns null when called.

When to use

Use when you need a thunk that returns null on every invocation.

Signature

declare const constNull: LazyArg<null>;

constTrue

Added in v2.0.0 Source

Returns true when called.

When to use

Use when you need a thunk that returns true on every invocation.

Signature

declare const constTrue: LazyArg<boolean>;

Returns undefined when called.

When to use

Use when you need a thunk that returns undefined on every invocation.

Signature

declare const constUndefined: LazyArg<undefined>;

constVoid

Added in v2.0.0 Source

Returns no meaningful value when called.

When to use

Use when you need a thunk that is called only for its effect and has no meaningful return value.

Signature

declare const constVoid: LazyArg<void>;

Constructors

constant

Added in v2.0.0 Source

Creates a zero-argument function that always returns the provided value.

When to use

Use when you need a thunk or callback that returns the same value on every invocation.

Signature

declare function constant<A>(value: A): LazyArg<A>;

Models

FunctionN type

Added in v2.0.0 Source

Represents a function with multiple arguments.

When to use

Use to describe a function whose argument list is represented as a tuple type.

Signature

type FunctionN<A extends ReadonlyArray<unknown>, B> = (...args: A) => B;

LazyArg type

Added in v2.0.0 Source

A zero-argument function that produces a value when invoked.

When to use

Use to type a lazy value provider that should not run until called.

Signature

type LazyArg<A> = () => A;

Utility Types

absurd

Added in v2.0.0 Source

Marks an impossible branch by accepting a never value and returning any type.

When to use

Use when you need a return value in a branch that exhaustive checks prove cannot be reached.

Gotchas

Calling absurd throws, because a value of type never should be impossible at runtime.

Signature

declare function absurd<A>(_: never): A;

cast

Added in v4.0.0 Source

Returns the input value with a different static type.

When to use

Use when you need an explicit type-level cast and accept that the value is returned unchanged at runtime.

Gotchas

This is a type-level cast only; it performs no runtime validation or conversion.

See

  • satisfies for checking assignability without changing the resulting type

Signature

declare const cast: <A, B>(a: A) => B;

FunctionTypeLambda interface

Added in v2.0.0 Source

Type lambda for function types, used for higher-kinded type operations.

When to use

Use when defining higher-kinded abstractions that must accept function types as one of their type-lambda inputs.

Signature

interface FunctionTypeLambda extends TypeLambda {
  readonly type: (a: unknown) => unknown;
}

hole

Added in v2.0.0 Source

Creates a compile-time placeholder for a value of any type.

When to use

Use as a temporary typed placeholder while developing incomplete code.

Gotchas

hole is intended for temporary development use. If the placeholder is evaluated at runtime, it throws.

Signature

declare const hole: <T>() => T;

satisfies

Added in v2.0.0 Source

Ensures that the type of an expression matches some type, without changing the resulting type of that expression.

When to use

Use to check assignability while preserving the expression's precise inferred type.

See

  • cast for changing only the static TypeScript type

Signature

declare function satisfies<A>(): <B>(b: B) => B;