Skip to content

Tuple

Works with fixed-length arrays, also called tuples.

The runtime helpers in this module create new tuples instead of mutating their inputs, and the types preserve element positions where possible. The helpers cover tuple construction, indexed access, selecting or removing positions, appending values, transforming elements, renaming indices, mapping typed positions, and deriving comparison or combination helpers for tuple shapes.

17 exports Added in v2.0.0 Source

Combining

Appends a single element to the end of a tuple.

When to use

Use when you need the appended value to remain part of the tuple's type-level shape and preserve literal element positions.

Details

The result type is [...T, E], preserving all existing element types.

See

Signature

declare const appendElement: {
  <E>(element: E): <T extends readonly Array<unknown>>(self: T) => [...Array<T>, E];
  <T extends readonly Array<unknown>, E>(self: T, element: E): [...Array<T>, E];
}

Concatenates two tuples into a single tuple.

When to use

Use to append all elements from one tuple to another tuple.

Details

The result type is [...T1, ...T2], preserving all element types from both tuples. Neither input tuple is mutated; a fresh tuple is returned.

See

Signature

declare const appendElements: {
  <T2 extends readonly Array<unknown>>(that: T2): <T1 extends readonly Array<unknown>>(self: T1) => [...Array<T1>, ...Array<T2>];
  <T1 extends readonly Array<unknown>, T2 extends readonly Array<unknown>>(self: T1, that: T2): [...Array<T1>, ...Array<T2>];
}

makeCombiner

Added in v4.0.0 Source

Creates a Combiner for a tuple shape by providing a Combiner for each position. When two tuples are combined, each element is merged using its corresponding combiner.

When to use

Use when you need to merge two same-shape tuples by combining each position independently, such as summing counters or concatenating strings.

See

  • makeReducer – like makeCombiner but with an initial value

Signature

declare function makeCombiner<A extends readonly Array<unknown>>(combiners: { [K in string | number | symbol]: Combiner<A[K]> }): Combiner<A>

Constructors

make

Added in v2.0.0 Source

Creates a tuple from the provided arguments.

When to use

Use when you need a properly typed tuple without writing [a, b, c] as const or another manual cast.

Details

The returned value has the exact tuple type, with each element's literal type preserved.

See

  • get – access a single element by index
  • appendElement – append an element to a tuple

Signature

declare function make<Elements extends readonly Array<unknown>>(...elements: [...Array<Elements>]): [...Array<Elements>]

Filtering

omit

Added in v4.0.0 Source

Creates a new tuple with the elements at the specified indices removed.

When to use

Use to drop elements from a tuple by position.

Details

Elements not at the specified indices are kept in their original order.

See

  • pick – the inverse (keep only specified indices)

Signature

declare const omit: {
  <T extends readonly Array<unknown>, I extends readonly Array<Exclude<Partial<T>["length"], T["length"]>>>(indices: I): (self: T) => _BuildTuple<T, Exclude<Exclude<Partial<T>["length"], T["length"]>, I[number]>>;
  <T extends readonly Array<unknown>, I extends readonly Array<Exclude<Partial<T>["length"], T["length"]>>>(self: T, indices: I): _BuildTuple<T, Exclude<Exclude<Partial<T>["length"], T["length"]>, I[number]>>;
}

pick

Added in v4.0.0 Source

Creates a new tuple containing only the elements at the specified indices.

When to use

Use to select a subset of elements from a tuple by position.

Details

The result order matches the order of the provided indices.

See

  • omit – the inverse (exclude indices instead)
  • get – extract a single element

Signature

declare const pick: {
  <T extends readonly Array<unknown>, I extends readonly Array<Exclude<Partial<T>["length"], T["length"]>>>(indices: I): (self: T) => PickTuple<T, I>;
  <T extends readonly Array<unknown>, I extends readonly Array<Exclude<Partial<T>["length"], T["length"]>>>(self: T, indices: I): PickTuple<T, I>;
}

Folding

makeReducer

Added in v4.0.0 Source

Creates a Reducer for a tuple shape by providing a Reducer for each position. The initial value is derived from each position's Reducer.initialValue. When reducing a collection of tuples, each element is combined independently.

When to use

Use when you need to fold same-shape tuples by accumulating each position independently into one summary tuple.

See

  • makeCombiner – like makeReducer but without an initial value

Signature

declare function makeReducer<A extends readonly Array<unknown>>(reducers: { [K in string | number | symbol]: Reducer<A[K]> }): Reducer<A>

Getters

get

Added in v4.0.0 Source

Retrieves the element at the specified index from a tuple.

When to use

Use when a single tuple element should be extracted in a pipeline.

Details

The index is constrained to valid tuple positions at the type level.

See

  • make – create a tuple
  • pick – extract multiple elements into a new tuple

Signature

declare const get: {
  <T extends readonly Array<unknown>, I extends never>(index: I): (self: T) => T[I];
  <T extends readonly Array<unknown>, I extends never>(self: T, index: I): T[I];
}

Guards

isTupleOf

Added in v3.3.0 Source

Checks whether a readonly array has exactly n elements.

When to use

Use when you need a Predicate guard for exact tuple length that narrows ReadonlyArray<T> to TupleOf<N, T>.

Details

This only checks length, not element types, and returns a refinement on the array type.

See

Signature

declare const isTupleOf: {
  <N extends number>(n: N): <T>(self: readonly Array<T>) => self is TupleOf<N, T>;
  <T, N extends number>(self: readonly Array<T>, n: N): self is TupleOf<N, T>;
}

Checks whether a readonly array has at least n elements.

When to use

Use when you need a Predicate guard for tuple-like minimum length that narrows ReadonlyArray<T> to TupleOfAtLeast<N, T>.

Details

This only checks length, not element types, and returns a refinement on the array type.

See

Signature

declare const isTupleOfAtLeast: {
  <N extends number>(n: N): <T>(self: readonly Array<T>) => self is [...Array<TupleOf<N, T>>, ...Array<T>];
  <T, N extends number>(self: readonly Array<T>, n: N): self is [...Array<TupleOf<N, T>>, ...Array<T>];
}

Instances

Creates an Equivalence for tuples by comparing corresponding elements using the provided per-position Equivalences. Two tuples are equivalent when all their corresponding elements are equivalent.

When to use

Use when you need an Equivalence to compare tuples element-by-element.

Details

This is an alias of Equivalence.Tuple.

See

Signature

declare const makeEquivalence: <Elements extends readonly Array<Equivalence<any>>>(elements: Elements) => Equivalence<{ [I in string | number | symbol]: [Elements[I]] extends [Equivalence<A>] ? A : never }>

Mapping

evolve

Added in v4.0.0 Source

Transforms elements of a tuple by providing an array of transform functions. Each function applies to the element at the same position. Positions beyond the array's length are copied unchanged.

When to use

Use when you want to update the first N elements while keeping the rest.

Details

Each transform function receives the current value and can return a different type.

See

  • map – apply the same transformation to all elements
  • renameIndices – swap element positions

Signature

declare const evolve: {
  <T extends readonly Array<unknown>, E extends Evolver<T>>(evolver: E): (self: T) => Evolved<T, E>;
  <T extends readonly Array<unknown>, E extends Evolver<T>>(self: T, evolver: E): Evolved<T, E>;
}

map

Added in v3.9.0 Source

Applies a Struct.Lambda transformation to every element in a tuple.

When to use

Use when you want to apply the same transformation to every tuple element.

Details

The lambda lets the compiler track the output type for each element.

Gotchas

The lambda must be created with Struct.lambda; a plain function will not type-check.

See

  • mapPick – apply a lambda only to selected indices
  • mapOmit – apply a lambda to all indices except selected ones
  • evolve – apply different functions to different indices

Signature

declare const map: {
  <L extends Lambda>(lambda: L): <T extends readonly Array<unknown>>(self: T) => { [K in string | number | symbol]: Apply<L, T[K]> };
  <T extends readonly Array<unknown>, L extends Lambda>(self: T, lambda: L): { [K in string | number | symbol]: Apply<L, T[K]> };
}

mapOmit

Added in v4.0.0 Source

Applies a Struct.Lambda transformation to all elements except those at the specified indices; the excluded elements are copied unchanged.

When to use

Use when most elements should be transformed but a few should be preserved.

See

  • map – apply a lambda to all elements
  • mapPick – apply a lambda only to selected indices

Signature

declare const mapOmit: {
  <T extends readonly Array<unknown>, I extends readonly Array<Exclude<Partial<T>["length"], T["length"]>>, L extends Lambda>(indices: I, lambda: L): (self: T) => { [K in string | number | symbol]: K extends `${I[number]}` ? T[K] : Apply<L, T[K]> };
  <T extends readonly Array<unknown>, I extends readonly Array<Exclude<Partial<T>["length"], T["length"]>>, L extends Lambda>(self: T, indices: I, lambda: L): { [K in string | number | symbol]: K extends `${I[number]}` ? T[K] : Apply<L, T[K]> };
}

mapPick

Added in v4.0.0 Source

Applies a Struct.Lambda transformation only to the elements at the specified indices; all other elements are copied unchanged.

When to use

Use when you want to apply the same transformation to a subset of positions.

See

  • map – apply a lambda to all elements
  • mapOmit – apply a lambda to all elements except selected ones

Signature

declare const mapPick: {
  <T extends readonly Array<unknown>, I extends readonly Array<Exclude<Partial<T>["length"], T["length"]>>, L extends Lambda>(indices: I, lambda: L): (self: T) => { [K in string | number | symbol]: K extends `${I[number]}` ? Apply<L, T[K]> : T[K] };
  <T extends readonly Array<unknown>, I extends readonly Array<Exclude<Partial<T>["length"], T["length"]>>, L extends Lambda>(self: T, indices: I, lambda: L): { [K in string | number | symbol]: K extends `${I[number]}` ? Apply<L, T[K]> : T[K] };
}

Ordering

makeOrder

Added in v4.0.0 Source

Creates an Order for tuples by comparing corresponding elements using the provided per-position Orders. Elements are compared left-to-right; the first non-zero comparison determines the result.

When to use

Use when you need to sort fixed-position arrays lexicographically, with each position using its own ordering rule.

Details

This is an alias of Order.Tuple.

See

Signature

declare const makeOrder: <Elements extends readonly Array<Order<any>>>(elements: Elements) => Order<{ [I in string | number | symbol]: [Elements[I]] extends [Order<A>] ? A : never }>

Transforming

Renames tuple indices by providing an array of stringified source indices. Each position in the array specifies which index to read from (e.g., ["2", "1", "0"] reverses a 3-element tuple).

When to use

Use to reorder tuple elements while preserving index-specific types.

Details

The mapping returns a tuple in the requested index order.

Gotchas

The mapping uses stringified source indices, not arbitrary names.

See

  • evolve – transform element values instead of positions

Signature

declare const renameIndices: {
  <T extends readonly Array<unknown>, M extends { [I in string | number | symbol]: `${keyof T & string}` }>(mapping: M): (self: T) => { [I in string | number | symbol]: I extends keyof M ? M[I] extends keyof T ? T[any[any]] : T[I] : T[I] };
  <T extends readonly Array<unknown>, M extends { [I in string | number | symbol]: `${keyof T & string}` }>(self: T, mapping: M): { [I in string | number | symbol]: I extends keyof M ? M[I] extends keyof T ? T[any[any]] : T[I] : T[I] };
}