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.
Caching
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) => OmemoizeIdempotent
Creates a memoized idempotent object transformation that caches both inputs and their outputs by object identity.
When to use
Use when an object transformation is idempotent and its output can be safely reused as a fixed point.
Details
After computing an input, the returned function caches both the input and the output. Calling it with either reference returns the output without invoking the supplied function again.
Gotchas
The returned function treats each computed output as a fixed point. If applying the supplied function to an output would produce an observably different value, this memoization changes that behavior.
See
- memoize for memoizing functions without an idempotence requirement
Signature
declare function memoizeIdempotent<A extends object>(f: (a: A) => A): (a: A) => ACombinators
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) => BExample
(Applying an argument to a function)
import { Function, pipe, String } from "effect"
pipe(String.length, Function.apply("hello")) // => 5Composes 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
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;}Example
(Composing two functions)
import { Function } from "effect"
const increment = (n: number) => n + 1const square = (n: number) => n * n
Function.compose(increment, square)(2) // => 9Creates 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;}Example
(Selecting data-first or data-last style by arity)
import { Function, pipe } from "effect"
const sum = Function.dual< (that: number) => (self: number) => number, (self: number, that: number) => number>(2, (self, that) => self + that)
sum(2, 3) // => 5pipe(2, sum(3)) // => 5Example
(Defining overloads with call signatures)
import { Function, pipe } from "effect"
const sum: { (that: number): (self: number) => number (self: number, that: number): number} = Function.dual(2, (self: number, that: number): number => self + that)
sum(2, 3) // => 5pipe(2, sum(3)) // => 5Example
(Selecting data-first or data-last style with a predicate)
import { Function, pipe } from "effect"
const sum = Function.dual< (that: number) => (self: number) => number, (self: number, that: number) => number>( (args) => args.length === 2, (self, that) => self + that)
sum(2, 3) // => 5pipe(2, sum(3)) // => 5Reverses 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) => CExample
(Flipping curried arguments)
import { Function } from "effect"
const f = (a: number) => (b: string) => a - b.length
Function.flip(f)("aaa")(2) // => -1Performs 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
Signature
declare function flow<A extends readonly Array<unknown>, B = never>(ab: (...a: A) => B): (...a: A) => Bdeclare function flow<A extends readonly Array<unknown>, B = never, C = never>(ab: (...a: A) => B, bc: (b: B) => C): (...a: A) => Cdeclare 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) => Ddeclare 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) => Edeclare 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) => Fdeclare 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) => Gdeclare 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) => Hdeclare 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) => Ideclare 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) => JExample
(Composing functions left to right)
import { flow } from "effect"
const len = (s: string): number => s.lengthconst double = (n: number): number => n * 2
const f = flow(len, double)
f("aaa") // => 6Returns 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): AExample
(Returning the same value)
import { identity } from "effect"
identity(5) // => 5Pipes 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.
Example (Piping values through functions)
In this example, 1 is passed to the first function, and each result becomes
the input for the next function.
Example (Rewriting method chains with pipe)
The same transformation can be written with data-last functions.
Signature
declare function pipe<A>(a: A): Adeclare function pipe<A, B = never>(a: A, ab: (a: A) => B): Bdeclare function pipe<A, B = never, C = never>(a: A, ab: (a: A) => B, bc: (b: B) => C): Cdeclare function pipe<A, B = never, C = never, D = never>(a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): Ddeclare 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): Edeclare 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): Fdeclare 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): Gdeclare 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): Hdeclare 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): Ideclare 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): Jdeclare 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): Kdeclare 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): Ldeclare 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): Mdeclare 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): Ndeclare 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): Odeclare 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): Pdeclare 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): Qdeclare 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): Rdeclare 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): Sdeclare 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): TExample
(Piping values through functions)
import { pipe } from "effect"
pipe( 1, (n) => n + 1, (n) => n * 2, (n) => `result: ${n}`) // => "result: 4"Example
(Rewriting method chains with pipe)
import { Array, pipe } from "effect"
const numbers = [1, 2, 3, 4]const double = (n: number) => n * 2const greaterThanFour = (n: number) => n > 4
pipe( numbers, Array.map(double), Array.filter(greaterThanFour)) // => [6, 8]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): BExample
(Discarding the first argument)
import { Function } from "effect"
Function.SK(0, "hello") // => "hello"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) => BExample
(Converting arguments to a tuple)
import { Function } from "effect"
const sumTupled = Function.tupled((x: number, y: number): number => x + y)
sumTupled([1, 2]) // => 3Converts 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) => BExample
(Converting a tuple to arguments)
import { Function } from "effect"
const getFirst = Function.untupled(<A, B>(tuple: [A, B]): A => tuple[0])
getFirst(1, 2) // => 1Constants
constFalse
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>Example
(Returning false from a thunk)
import { Function } from "effect"
Function.constFalse() // => falseReturns null when called.
When to use
Use when you need a thunk that returns null on every invocation.
Signature
declare const constNull: LazyArg<null>Example
(Returning null from a thunk)
import { Function } from "effect"
Function.constNull() // => nullReturns true when called.
When to use
Use when you need a thunk that returns true on every invocation.
Signature
declare const constTrue: LazyArg<boolean>Example
(Returning true from a thunk)
import { Function } from "effect"
Function.constTrue() // => trueconstUndefined
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>Example
(Returning undefined from a thunk)
import { Function } from "effect"
Function.constUndefined() // => undefinedReturns 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>Example
(Returning void from a thunk)
import { Function } from "effect"
Function.constVoid() // => undefinedConstructors
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>Example
(Creating a constant thunk)
import { Function } from "effect"
const constNull = Function.constant(null)
constNull() // => nullconstNull() // => nullModels
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) => BExample
(Typing a variadic function)
import type { Function } from "effect"
const sum: Function.FunctionN<[number, number], number> = (a, b) => a + bsum(2, 3) // => 5A 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> = () => AExample
(Creating a lazy argument)
import { Function } from "effect"
const constNull: Function.LazyArg<null> = Function.constant(null)constNull() // => nullUtility Types
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): AExample
(Handling impossible values)
import { absurd } from "effect"
const handleNever = (value: never) => { return absurd(value) // This will throw an error if called}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) => BFunctionTypeLambda interface
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;}Example
(Creating a function type with a type lambda)
import type { Function, HKT } from "effect"
// Create a function type using the type lambdatype StringToNumber = HKT.Kind<Function.FunctionTypeLambda, string, never, never, number>// Equivalent to: (a: string) => numberCreates 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>() => TExample
(Creating a development placeholder)
import { hole } from "effect"
// Intentionally not called: `hole` throws if the placeholder is evaluated.const buildUser = (id: number): { readonly id: number; readonly name: string } => ({ id, name: hole<string>()})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) => BExample
(Checking an expression against a type)
import { Function } from "effect"
const test1 = Function.satisfies<number>()(5 as const) // => 5// ^? const test: 5// @ts-expect-errorconst test2 = Function.satisfies<string>()(5)// ^? Argument of type 'number' is not assignable to parameter of type 'string'