Array
The Array module is a functional toolkit for working with JavaScript arrays. It operates on plain ReadonlyArray<A> values — the built-in array type — and adds constructors, transformations, searches, folds, grouping, sorting, and set-like operations around them.
Three properties hold across the whole module:
- Nothing mutates. Operations that transform, reorder, or update a collection allocate a new array; your input is left untouched.
- Functions are dual. Every combinator can be called data-first (
Array.map(xs, f)) or data-last for pipelines (pipe(xs, Array.map(f))). - Non-emptiness is tracked in the type.
NonEmptyReadonlyArray<A>(and its mutable twinNonEmptyArray<A>) encode “at least one element” at the type level, so APIs likeheadNonEmptycan returnAdirectly instead ofOption<A>.
import { Array } from "effect"
// import the namespace — `Array` shadows the TS global on purpose,// and Array.Array still exposes the native constructor if you need it.A worked pipeline
Section titled “A worked pipeline”Most real code is a pipe of small steps. Here is a filter / map / group sequence in data-last style.
import { Array, pipe } from "effect"
const orders = [ { id: 1, region: "us", total: 120 }, { id: 2, region: "eu", total: 80 }, { id: 3, region: "us", total: 50 }, { id: 4, region: "eu", total: 200 }]
const byRegion = pipe( orders, Array.filter((o) => o.total >= 60), // drop small orders Array.map((o) => ({ ...o, total: o.total * 1.1 })), // add 10% fee Array.groupBy((o) => o.region) // bucket by region)
console.log(byRegion)// {// us: [{ id: 1, region: "us", total: 132 }],// eu: [{ id: 2, region: "eu", total: 88 }, { id: 4, region: "eu", total: 220 }]// }NonEmpty tracking
Section titled “NonEmpty tracking”A NonEmptyReadonlyArray<A> is just readonly [A, ...Array<A>]. Because the first slot is guaranteed, total functions can skip Option:
import { Array } from "effect"
declare const xs: Array.NonEmptyReadonlyArray<number>
Array.headNonEmpty(xs) // : number (not Option<number>)Array.head([1, 2, 3]) // : Option<number> on a plain arrayisArrayNonEmpty / isReadonlyArrayNonEmpty are refinements: passing the guard narrows the value so the NonEmpty APIs become available.
import { Array } from "effect"
const parse = (input: ReadonlyArray<number>) => { if (Array.isReadonlyArrayNonEmpty(input)) { // `input` is now NonEmptyReadonlyArray<number> return Array.headNonEmpty(input) // number, no Option } return 0}Operations that can prove the result is non-empty preserve the type: map, sort, reverse, prepend, append, intersperse, rotate, copy, dedupe, and the *NonEmpty variants all return NonEmptyArray when given non-empty input.
Reference
Section titled “Reference”Constructors
Section titled “Constructors”Creates a NonEmptyArray from one or more literal elements; the element type is the union of all arguments.
import { Array } from "effect"
Array.make(1, 2, 3) // => [1, 2, 3] (NonEmptyArray<number>)allocate
Section titled “allocate”Creates an Array of the given length with uninitialized slots, typed as A | undefined. Fill it imperatively.
import { Array } from "effect"
Array.allocate<number>(3).length // => 3makeBy
Section titled “makeBy”Builds a NonEmptyArray of length n (normalized to >= 1) where element i is f(i).
import { Array } from "effect"
Array.makeBy(5, (n) => n * 2) // => [0, 2, 4, 6, 8]Creates a NonEmptyArray of consecutive integers, inclusive on both ends. If start > end, returns [start].
import { Array } from "effect"
Array.range(1, 3) // => [1, 2, 3]Array.range(5, 2) // => [5]replicate
Section titled “replicate”Creates a NonEmptyArray with a value repeated n times (n normalized to >= 1).
import { Array } from "effect"
Array.replicate("a", 3) // => ["a", "a", "a"]fromIterable
Section titled “fromIterable”Converts any Iterable to an Array. If the input is already an array it is returned by reference (no copy) — use copy for a fresh array.
import { Array } from "effect"
Array.fromIterable(new Set([1, 2, 3])) // => [1, 2, 3]ensure
Section titled “ensure”Normalizes a value that may be a single element or an array into an array. Handy for APIs that accept A | Array<A>.
import { Array } from "effect"
Array.ensure("a") // => ["a"]Array.ensure(["a", "b"]) // => ["a", "b"]fromRecord
Section titled “fromRecord”Converts a record into an array of [key, value] tuples, following Object.entries order.
import { Array } from "effect"
Array.fromRecord({ a: 1, b: 2 }) // => [["a", 1], ["b", 2]]fromOption
Section titled “fromOption”Converts an Option to an array: Some(a) becomes [a], None becomes [].
import { Array, Option } from "effect"
Array.fromOption(Option.some(1)) // => [1]Array.fromOption(Option.none()) // => []Creates a typed empty array.
import { Array } from "effect"
Array.empty<number>() // => []Wraps a single value in a NonEmptyArray.
import { Array } from "effect"
Array.of(1) // => [1]unfold
Section titled “unfold”Builds an array by repeatedly applying a function to a seed. Return Option.some([element, nextSeed]) to continue, Option.none() to stop.
import { Array, Option } from "effect"
Array.unfold(1, (n) => (n <= 5 ? Option.some([n, n + 1]) : Option.none()))// => [1, 2, 3, 4, 5]Concatenation
Section titled “Concatenation”prepend
Section titled “prepend”Adds a single element to the front, always returning a NonEmptyArray.
import { Array } from "effect"
Array.prepend([2, 3, 4], 1) // => [1, 2, 3, 4]prependAll
Section titled “prependAll”Prepends all elements of a prefix iterable. Non-empty if either input is non-empty.
import { Array } from "effect"
Array.prependAll([2, 3], [0, 1]) // => [0, 1, 2, 3]append
Section titled “append”Adds a single element to the end, always returning a NonEmptyArray.
import { Array } from "effect"
Array.append([1, 2, 3], 4) // => [1, 2, 3, 4]appendAll
Section titled “appendAll”Concatenates two iterables. Non-empty if either input is non-empty.
import { Array } from "effect"
Array.appendAll([1, 2], [3, 4]) // => [1, 2, 3, 4]Predicates and guards
Section titled “Predicates and guards”isArray
Section titled “isArray”Type guard for native arrays, narrowing to Array<unknown>. Delegates to globalThis.Array.isArray.
import { Array } from "effect"
Array.isArray([1, 2, 3]) // => trueArray.isArray(null) // => falseisArrayEmpty
Section titled “isArrayEmpty”Checks whether a mutable Array is empty, narrowing to [].
import { Array } from "effect"
Array.isArrayEmpty([]) // => trueArray.isArrayEmpty([1]) // => falseisReadonlyArrayEmpty
Section titled “isReadonlyArrayEmpty”Readonly counterpart of isArrayEmpty, narrowing to readonly [].
import { Array } from "effect"
Array.isReadonlyArrayEmpty([] as ReadonlyArray<number>) // => trueisArrayNonEmpty
Section titled “isArrayNonEmpty”Checks whether a mutable Array is non-empty, narrowing to NonEmptyArray.
import { Array } from "effect"
Array.isArrayNonEmpty([1, 2, 3]) // => trueArray.isArrayNonEmpty([]) // => falseisReadonlyArrayNonEmpty
Section titled “isReadonlyArrayNonEmpty”Readonly counterpart of isArrayNonEmpty, narrowing to NonEmptyReadonlyArray.
import { Array } from "effect"
Array.isReadonlyArrayNonEmpty([1] as ReadonlyArray<number>) // => trueAccessing
Section titled “Accessing”length
Section titled “length”The number of elements, as a composable function.
import { Array } from "effect"
Array.length([1, 2, 3]) // => 3Reads an element at an index safely, returning Option. The index is floored; out-of-bounds returns None.
import { Array } from "effect"
Array.get([1, 2, 3], 1) // => Option.some(2)Array.get([1, 2, 3], 10) // => Option.none()getUnsafe
Section titled “getUnsafe”Reads an element at an index, throwing "Index out of bounds: <i>" if invalid. Prefer get for safe access.
import { Array } from "effect"
Array.getUnsafe([1, 2, 3], 1) // => 2// Array.getUnsafe([1, 2, 3], 10) // throws ErrorThe first element as an Option, or None for an empty array.
import { Array } from "effect"
Array.head([1, 2, 3]) // => Option.some(1)Array.head([]) // => Option.none()headNonEmpty
Section titled “headNonEmpty”The first element of a NonEmptyReadonlyArray, returned directly without Option.
import { Array } from "effect"
Array.headNonEmpty([1, 2, 3]) // => 1The last element as an Option, or None for an empty array.
import { Array } from "effect"
Array.last([1, 2, 3]) // => Option.some(3)Array.last([]) // => Option.none()lastNonEmpty
Section titled “lastNonEmpty”The last element of a NonEmptyReadonlyArray, returned directly.
import { Array } from "effect"
Array.lastNonEmpty([1, 2, 3]) // => 3All elements except the first, as an Option (allocates via slice(1)).
import { Array } from "effect"
Array.tail([1, 2, 3]) // => Option.some([2, 3])Array.tail([]) // => Option.none()tailNonEmpty
Section titled “tailNonEmpty”All elements after the first of a NonEmptyReadonlyArray.
import { Array } from "effect"
Array.tailNonEmpty([1, 2, 3]) // => [2, 3]All elements except the last, as an Option (allocates via slice(0, -1)).
import { Array } from "effect"
Array.init([1, 2, 3]) // => Option.some([1, 2])Array.init([]) // => Option.none()initNonEmpty
Section titled “initNonEmpty”All elements before the last of a NonEmptyReadonlyArray.
import { Array } from "effect"
Array.initNonEmpty([1, 2, 3]) // => [1, 2]unprepend
Section titled “unprepend”Splits a NonEmptyReadonlyArray into [head, tail].
import { Array } from "effect"
Array.unprepend([1, 2, 3, 4]) // => [1, [2, 3, 4]]unappend
Section titled “unappend”Splits a NonEmptyReadonlyArray into [init, last].
import { Array } from "effect"
Array.unappend([1, 2, 3, 4]) // => [[1, 2, 3], 4]Taking, dropping, slicing
Section titled “Taking, dropping, slicing”Keeps the first n elements (n clamped to [0, length]).
import { Array } from "effect"
Array.take([1, 2, 3, 4, 5], 3) // => [1, 2, 3]takeRight
Section titled “takeRight”Keeps the last n elements (n clamped to [0, length]).
import { Array } from "effect"
Array.takeRight([1, 2, 3, 4, 5], 3) // => [3, 4, 5]takeWhile
Section titled “takeWhile”Keeps the leading prefix while the predicate holds, stopping at the first failure. Supports refinements. The predicate receives (element, index).
import { Array } from "effect"
Array.takeWhile([1, 3, 2, 4, 1], (x) => x < 4) // => [1, 3, 2]takeWhileFilter
Section titled “takeWhileFilter”Keeps the leading prefix while a Result-returning filter succeeds, collecting the transformed success values. Stops at the first failure.
import { Array, Result } from "effect"
Array.takeWhileFilter([1, 2, 9, 3], (n) => n < 5 ? Result.succeed(n * 10) : Result.failVoid)// => [10, 20]Splits into the longest matching prefix and the rest in a single pass — like [takeWhile(p), dropWhile(p)]. Supports refinements on the prefix.
import { Array } from "effect"
Array.span([1, 3, 2, 4, 5], (x) => x % 2 === 1) // => [[1, 3], [2, 4, 5]]Removes the first n elements (n clamped to [0, length]).
import { Array } from "effect"
Array.drop([1, 2, 3, 4, 5], 2) // => [3, 4, 5]dropRight
Section titled “dropRight”Removes the last n elements (n clamped to [0, length]).
import { Array } from "effect"
Array.dropRight([1, 2, 3, 4, 5], 2) // => [1, 2, 3]dropWhile
Section titled “dropWhile”Removes the leading prefix while the predicate holds, returning the rest.
import { Array } from "effect"
Array.dropWhile([1, 2, 3, 4, 5], (x) => x < 4) // => [4, 5]dropWhileFilter
Section titled “dropWhileFilter”Removes the leading prefix while a Result-returning filter succeeds, returning the remaining original elements.
import { Array, Result } from "effect"
Array.dropWhileFilter([1, 2, 9, 3], (n) => n < 5 ? Result.succeed(n) : Result.failVoid)// => [9, 3]splitAt
Section titled “splitAt”Splits an iterable into a prefix and suffix at the given index (n floored, may be 0).
import { Array } from "effect"
Array.splitAt([1, 2, 3, 4, 5], 3) // => [[1, 2, 3], [4, 5]]splitAtNonEmpty
Section titled “splitAtNonEmpty”Splits a NonEmptyReadonlyArray so the first part is guaranteed non-empty (n clamped to >= 1).
import { Array } from "effect"
Array.splitAtNonEmpty(["a", "b", "c", "d"], 2) // => [["a", "b"], ["c", "d"]]Splits an iterable into n roughly equal chunks; the last chunk may be shorter.
import { Array } from "effect"
Array.split([1, 2, 3, 4, 5, 6, 7, 8], 3) // => [[1, 2, 3], [4, 5, 6], [7, 8]]splitWhere
Section titled “splitWhere”Splits at the first element matching the predicate; the matching element starts the second array.
import { Array } from "effect"
Array.splitWhere([1, 2, 3, 4, 5], (n) => n > 3) // => [[1, 2, 3], [4, 5]]chunksOf
Section titled “chunksOf”Splits an iterable into non-overlapping chunks of length n; the last may be shorter. Each chunk is a NonEmptyArray. chunksOf(n)([]) is [].
import { Array } from "effect"
Array.chunksOf([1, 2, 3, 4, 5], 2) // => [[1, 2], [3, 4], [5]]window
Section titled “window”Creates overlapping sliding windows of size n. Returns [] if n <= 0 or the array is shorter than n.
import { Array } from "effect"
Array.window([1, 2, 3, 4, 5], 3) // => [[1, 2, 3], [2, 3, 4], [3, 4, 5]]Array.window([1, 2], 6) // => []Creates a shallow copy, preserving NonEmptyArray in the type. Useful when you need a distinct reference (unlike fromIterable, which returns arrays by reference).
import { Array } from "effect"
const original = [1, 2, 3]const copied = Array.copy(original)original === copied // => falsePads or truncates to exactly n elements: fills with fill if shorter, slices if longer. Returns [] when n <= 0.
import { Array } from "effect"
Array.pad([1, 2, 3], 6, 0) // => [1, 2, 3, 0, 0, 0]Array.pad([1, 2, 3], 2, 0) // => [1, 2]Repeatedly consumes prefixes via a function returning [value, rest], until the remaining array is empty. The basis for custom splitting/grouping.
import { Array } from "effect"
Array.chop([1, 2, 3, 4], (as): [number, Array<number>] => [as[0] * 2, as.slice(1)])// => [2, 4, 6, 8]Searching
Section titled “Searching”findFirstIndex
Section titled “findFirstIndex”The index of the first element matching the predicate, as an Option.
import { Array } from "effect"
Array.findFirstIndex([5, 3, 8, 9], (x) => x > 5) // => Option.some(2)findLastIndex
Section titled “findLastIndex”The index of the last element matching the predicate, as an Option.
import { Array } from "effect"
Array.findLastIndex([1, 3, 8, 9], (x) => x < 5) // => Option.some(1)findFirst
Section titled “findFirst”The first element matching a predicate, refinement, or Option-returning function (find-and-transform), as an Option.
import { Array } from "effect"
Array.findFirst([1, 2, 3, 4, 5], (x) => x > 3) // => Option.some(4)findFirstWithIndex
Section titled “findFirstWithIndex”Like findFirst, but returns Option.some([value, index]) for the first match.
import { Array } from "effect"
Array.findFirstWithIndex([1, 2, 3, 4, 5], (x) => x > 3) // => Option.some([4, 3])findLast
Section titled “findLast”The last element matching a predicate, refinement, or Option-returning function, searching from the end.
import { Array } from "effect"
Array.findLast([1, 2, 3, 4, 5], (n) => n % 2 === 0) // => Option.some(4)contains
Section titled “contains”Checks membership using Effect’s default equality (Equal.asEquivalence()).
import { Array } from "effect"
Array.contains(["a", "b", "c"], "c") // => truecontainsWith
Section titled “containsWith”Returns a membership-test function using a custom equivalence.
import { Array, pipe } from "effect"
const containsNum = Array.containsWith((a: number, b: number) => a === b)pipe([1, 2, 3], containsNum(3)) // => trueModifying
Section titled “Modifying”All of these return new arrays; the input is never mutated.
insertAt
Section titled “insertAt”Inserts an element at an index safely, returning Option<NonEmptyArray>. Valid indices are 0 to length (inserting at length appends).
import { Array } from "effect"
Array.insertAt(["a", "b", "c", "e"], 3, "d") // => Option.some(["a", "b", "c", "d", "e"])replace
Section titled “replace”Replaces the element at an index with a fixed value, returning Option. None if out of bounds.
import { Array } from "effect"
Array.replace([1, 2, 3], 1, 4) // => Option.some([1, 4, 3])modify
Section titled “modify”Applies a function to the element at an index, returning Option. None if out of bounds.
import { Array } from "effect"
Array.modify([1, 2, 3, 4], 2, (n) => n * 2) // => Option.some([1, 2, 6, 4])Array.modify([1, 2, 3, 4], 5, (n) => n * 2) // => Option.none()remove
Section titled “remove”Removes the element at an index; returns a copy of the original if the index is out of bounds.
import { Array } from "effect"
Array.remove([1, 2, 3, 4], 2) // => [1, 2, 4]Array.remove([1, 2, 3, 4], 5) // => [1, 2, 3, 4]reverse
Section titled “reverse”Reverses into a new array, preserving NonEmptyArray.
import { Array } from "effect"
Array.reverse([1, 2, 3, 4]) // => [4, 3, 2, 1]rotate
Section titled “rotate”Rotates by n steps: positive rotates right, negative rotates left, wrapping around. n is rounded; preserves NonEmptyArray.
import { Array } from "effect"
Array.rotate(["a", "b", "c", "d"], 2) // => ["c", "d", "a", "b"]intersperse
Section titled “intersperse”Inserts a separator between every pair of elements, preserving NonEmptyArray. Empty input yields empty output.
import { Array } from "effect"
Array.intersperse([1, 2, 3], 0) // => [1, 0, 2, 0, 3]modifyHeadNonEmpty
Section titled “modifyHeadNonEmpty”Transforms the first element of a NonEmptyReadonlyArray.
import { Array } from "effect"
Array.modifyHeadNonEmpty([1, 2, 3], (n) => n * 10) // => [10, 2, 3]setHeadNonEmpty
Section titled “setHeadNonEmpty”Replaces the first element of a NonEmptyReadonlyArray with a fixed value.
import { Array } from "effect"
Array.setHeadNonEmpty([1, 2, 3], 10) // => [10, 2, 3]modifyLastNonEmpty
Section titled “modifyLastNonEmpty”Transforms the last element of a NonEmptyReadonlyArray.
import { Array } from "effect"
Array.modifyLastNonEmpty([1, 2, 3], (n) => n * 2) // => [1, 2, 6]setLastNonEmpty
Section titled “setLastNonEmpty”Replaces the last element of a NonEmptyReadonlyArray with a fixed value.
import { Array } from "effect"
Array.setLastNonEmpty([1, 2, 3], 4) // => [1, 2, 4]Sorting
Section titled “Sorting”Sorts by an Order, preserving NonEmptyArray.
import { Array, Order } from "effect"
Array.sort([3, 1, 4, 1, 5], Order.Number) // => [1, 1, 3, 4, 5]sortWith
Section titled “sortWith”Sorts by a derived key using a mapping function plus an Order for that key. Equivalent to sort(Order.mapInput(order, f)).
import { Array, Order } from "effect"
Array.sortWith(["aaa", "b", "cc"], (s) => s.length, Order.Number) // => ["b", "cc", "aaa"]sortBy
Section titled “sortBy”Sorts by multiple Orders in sequence: later orders break ties from earlier ones. Data-last only; preserves NonEmptyArray.
import { Array, Order, pipe } from "effect"
type User = { name: string; age: number }const users: Array<User> = [ { name: "Alice", age: 30 }, { name: "Bob", age: 25 }, { name: "Charlie", age: 30 }]
pipe( users, Array.sortBy( Order.mapInput(Order.Number, (u: User) => u.age), Order.mapInput(Order.String, (u: User) => u.name) ))// => [{ name: "Bob", age: 25 }, { name: "Alice", age: 30 }, { name: "Charlie", age: 30 }]The minimum element of a NonEmptyReadonlyArray by an Order.
import { Array, Order } from "effect"
Array.min([3, 1, 2], Order.Number) // => 1The maximum element of a NonEmptyReadonlyArray by an Order.
import { Array, Order } from "effect"
Array.max([3, 1, 2], Order.Number) // => 3makeOrder
Section titled “makeOrder”Creates an Order for arrays from an element Order. Arrays are compared element-wise; ties go to the shorter array.
import { Array, Order } from "effect"
const arrayOrder = Array.makeOrder(Order.Number)arrayOrder([1, 2], [1, 3]) // => -1makeEquivalence
Section titled “makeEquivalence”Creates an Equivalence for arrays from an element Equivalence. Equal when lengths match and all elements are pairwise equivalent.
import { Array } from "effect"
const eq = Array.makeEquivalence<number>((a, b) => a === b)eq([1, 2, 3], [1, 2, 3]) // => trueZipping
Section titled “Zipping”Pairs elements by position; extra elements from the longer iterable are discarded. NonEmptyArray when both inputs are non-empty.
import { Array } from "effect"
Array.zip([1, 2, 3], ["a", "b"]) // => [[1, "a"], [2, "b"]]zipWith
Section titled “zipWith”Combines elements pairwise using a function; extra elements are discarded.
import { Array } from "effect"
Array.zipWith([1, 2, 3], [4, 5, 6], (a, b) => a + b) // => [5, 7, 9]Splits an array of pairs into two arrays — the inverse of zip.
import { Array } from "effect"
Array.unzip([[1, "a"], [2, "b"], [3, "c"]]) // => [[1, 2, 3], ["a", "b", "c"]]cartesian
Section titled “cartesian”Every [a, b] pair from two arrays as tuples. Result length is self.length * that.length.
import { Array } from "effect"
Array.cartesian([1, 2], ["a", "b"]) // => [[1, "a"], [1, "b"], [2, "a"], [2, "b"]]cartesianWith
Section titled “cartesianWith”Like cartesian, but applies a combiner to each pair.
import { Array } from "effect"
Array.cartesianWith([1, 2], ["a", "b"], (a, b) => `${a}-${b}`)// => ["1-a", "1-b", "2-a", "2-b"]Mapping and folding
Section titled “Mapping and folding”Transforms each element, preserving NonEmptyArray. The function receives (element, index).
import { Array } from "effect"
Array.map([1, 2, 3], (x) => x * 2) // => [2, 4, 6]flatMap
Section titled “flatMap”Maps each element to an array and flattens the results. NonEmptyArray when both input and every mapped array are non-empty.
import { Array } from "effect"
Array.flatMap([1, 2, 3], (x) => [x, x * 2]) // => [1, 2, 2, 4, 3, 6]flatten
Section titled “flatten”Flattens one level of nested arrays.
import { Array } from "effect"
Array.flatten([[1, 2], [], [3, 4], [5, 6]]) // => [1, 2, 3, 4, 5, 6]forEach
Section titled “forEach”Runs a side-effect for each element; returns nothing. The callback receives (element, index).
import { Array } from "effect"
Array.forEach([1, 2, 3], (n) => console.log(n)) // logs 1, 2, 3filterMap
Section titled “filterMap”Maps with a Result-returning filter, keeping only the success values. Failures are discarded.
import { Array, Result } from "effect"
Array.filterMap([1, 2, 3, 4], (n) => n % 2 === 0 ? Result.succeed(n * 10) : Result.failVoid)// => [20, 40]filter
Section titled “filter”Keeps only elements satisfying a predicate or refinement. Always returns a plain Array.
import { Array } from "effect"
Array.filter([1, 2, 3, 4], (x) => x % 2 === 0) // => [2, 4]partition
Section titled “partition”Evaluates each element with a Result-returning filter and keeps both sides, as [excluded, satisfying].
import { Array, Result } from "effect"
Array.partition([1, -2, 3], (n, i) => n > 0 ? Result.succeed(n + i) : Result.fail(`negative:${n}`))// => [["negative:-2"], [1, 5]]separate
Section titled “separate”Splits an array of existing Results into [failures, successes]. Equivalent to partition(identity).
import { Array, Result } from "effect"
Array.separate([Result.succeed(1), Result.fail("error"), Result.succeed(2)])// => [["error"], [1, 2]]reduce
Section titled “reduce”Folds left-to-right into a single value. The function receives (accumulator, element, index).
import { Array } from "effect"
Array.reduce([1, 2, 3], 0, (acc, n) => acc + n) // => 6reduceRight
Section titled “reduceRight”Folds right-to-left into a single value.
import { Array } from "effect"
Array.reduceRight([1, 2, 3], 0, (acc, n) => acc + n) // => 6mapAccum
Section titled “mapAccum”Maps while threading an accumulator through each step, returning [finalState, mappedArray]. The callback returns [nextState, mappedValue].
import { Array } from "effect"
Array.mapAccum([1, 2, 3], 0, (acc, n) => [acc + n, acc + n]) // => [6, [1, 3, 6]]extend
Section titled “extend”Applies a function to each suffix of the array; at index i the function receives self.slice(i).
import { Array } from "effect"
Array.extend([1, 2, 3], (as) => as.length) // => [3, 2, 1]Folds left-to-right keeping every intermediate accumulator. Output length is input.length + 1, always a NonEmptyArray (starts with the initial value).
import { Array } from "effect"
Array.scan([1, 2, 3, 4], 0, (acc, n) => acc + n) // => [0, 1, 3, 6, 10]scanRight
Section titled “scanRight”Folds right-to-left keeping every intermediate accumulator. Output ends with the initial value.
import { Array } from "effect"
Array.scanRight([1, 2, 3, 4], 0, (acc, n) => acc + n) // => [10, 9, 7, 4, 0]Checks whether all elements satisfy the predicate; supports refinements for narrowing.
import { Array } from "effect"
Array.every([2, 4, 6], (x) => x % 2 === 0) // => trueArray.every([2, 3, 6], (x) => x % 2 === 0) // => falseChecks whether at least one element satisfies the predicate, narrowing to NonEmptyReadonlyArray on success.
import { Array } from "effect"
Array.some([1, 3, 4], (x) => x % 2 === 0) // => trueArray.some([1, 3, 5], (x) => x % 2 === 0) // => falsecountBy
Section titled “countBy”Counts how many elements satisfy a predicate. Returns 0 for an empty iterable.
import { Array } from "effect"
Array.countBy([1, 2, 3, 4, 5], (n) => n % 2 === 0) // => 2Joins string elements with a separator.
import { Array } from "effect"
Array.join(["a", "b", "c"], "-") // => "a-b-c"Grouping and dedupe
Section titled “Grouping and dedupe”Groups consecutive equal elements using Effect’s default equality. Only adjacent equal values are grouped. Requires a NonEmptyReadonlyArray.
import { Array } from "effect"
Array.group([1, 1, 2, 2, 2, 3, 1]) // => [[1, 1], [2, 2, 2], [3], [1]]groupWith
Section titled “groupWith”Like group, but uses a custom equivalence.
import { Array } from "effect"
Array.groupWith(["a", "a", "b", "b", "c"], (x, y) => x === y)// => [["a", "a"], ["b", "b"], ["c"]]groupBy
Section titled “groupBy”Groups all elements into a record by a key-returning function (key must be string or symbol). Elements need not be adjacent.
import { Array } from "effect"
const people = [ { name: "Alice", team: "A" }, { name: "Bob", team: "B" }, { name: "Charlie", team: "A" }]
Array.groupBy(people, (p) => p.team)// => {// A: [{ name: "Alice", team: "A" }, { name: "Charlie", team: "A" }],// B: [{ name: "Bob", team: "B" }]// }dedupe
Section titled “dedupe”Removes all duplicates using default equality, keeping the first occurrence. Preserves NonEmptyArray.
import { Array } from "effect"
Array.dedupe([1, 2, 1, 3, 2, 4]) // => [1, 2, 3, 4]dedupeWith
Section titled “dedupeWith”Like dedupe, but uses a custom equivalence.
import { Array } from "effect"
Array.dedupeWith([1, 2, 2, 3, 3, 3], (a, b) => a === b) // => [1, 2, 3]dedupeAdjacent
Section titled “dedupeAdjacent”Removes only consecutive duplicates using default equality; non-adjacent repeats are kept.
import { Array } from "effect"
Array.dedupeAdjacent([1, 1, 2, 2, 3, 1]) // => [1, 2, 3, 1]dedupeAdjacentWith
Section titled “dedupeAdjacentWith”Like dedupeAdjacent, but uses a custom equivalence.
import { Array } from "effect"
Array.dedupeAdjacentWith([1, 1, 2, 2, 3], (a, b) => a === b) // => [1, 2, 3]Set operations
Section titled “Set operations”These use Effect’s Equal protocol by default; the *With variants take a custom equivalence.
Elements present in either array, deduplicated using default equality.
import { Array } from "effect"
Array.union([1, 2], [2, 3]) // => [1, 2, 3]unionWith
Section titled “unionWith”Like union, but uses a custom equivalence.
import { Array } from "effect"
Array.unionWith([1, 2], [2, 3], (a, b) => a === b) // => [1, 2, 3]intersection
Section titled “intersection”Elements present in both arrays (order from the first), using default equality.
import { Array } from "effect"
Array.intersection([1, 2, 3], [3, 4, 1]) // => [1, 3]intersectionWith
Section titled “intersectionWith”Like intersection, but uses a custom equivalence — useful for matching objects by a field.
import { Array, pipe } from "effect"
const a = [{ id: 1 }, { id: 2 }, { id: 3 }]const b = [{ id: 3 }, { id: 4 }, { id: 1 }]const eq = (x: { id: number }, y: { id: number }) => x.id === y.id
pipe(a, Array.intersectionWith(eq)(b)) // => [{ id: 1 }, { id: 3 }]difference
Section titled “difference”Elements in the first array that are not in the second, using default equality.
import { Array } from "effect"
Array.difference([1, 2, 3], [2, 3, 4]) // => [1]differenceWith
Section titled “differenceWith”Like difference, but uses a custom equivalence.
import { Array } from "effect"
Array.differenceWith<number>((a, b) => a === b)([1, 2, 3], [2, 3, 4]) // => [1]Option and Result interop
Section titled “Option and Result interop”getSomes
Section titled “getSomes”Extracts all Some values from an iterable of Options, discarding Nones.
import { Array, Option } from "effect"
Array.getSomes([Option.some(1), Option.none(), Option.some(2)]) // => [1, 2]getFailures
Section titled “getFailures”Extracts all failure values from an iterable of Results, discarding successes.
import { Array, Result } from "effect"
Array.getFailures([Result.succeed(1), Result.fail("err"), Result.succeed(2)]) // => ["err"]getSuccesses
Section titled “getSuccesses”Extracts all success values from an iterable of Results, discarding failures.
import { Array, Result } from "effect"
Array.getSuccesses([Result.succeed(1), Result.fail("err"), Result.succeed(2)]) // => [1, 2]liftPredicate
Section titled “liftPredicate”Lifts a predicate (or refinement) into an array-returning function: [value] if it holds, [] otherwise.
import { Array } from "effect"
const toEven = Array.liftPredicate((n: number) => n % 2 === 0)toEven(2) // => [2]toEven(1) // => []liftOption
Section titled “liftOption”Lifts an Option-returning function into one that returns an array: Some(a) becomes [a], None becomes [].
import { Array, Option } from "effect"
const parse = Array.liftOption((s: string) => { const n = Number(s) return isNaN(n) ? Option.none() : Option.some(n)})parse("123") // => [123]parse("abc") // => []liftResult
Section titled “liftResult”Lifts a Result-returning function: failures produce [], successes produce [value].
import { Array, Result } from "effect"
const parse = (s: string): Result.Result<number, Error> => isNaN(Number(s)) ? Result.fail(new Error("NaN")) : Result.succeed(Number(s))
const lifted = Array.liftResult(parse)lifted("42") // => [42]lifted("x") // => []fromNullishOr
Section titled “fromNullishOr”Converts a nullable value to an array: null/undefined becomes [], anything else becomes [value].
import { Array } from "effect"
Array.fromNullishOr(1) // => [1]Array.fromNullishOr(null) // => []liftNullishOr
Section titled “liftNullishOr”Lifts a nullable-returning function: null/undefined produces [], anything else produces [value].
import { Array } from "effect"
const parse = Array.liftNullishOr((s: string) => { const n = Number(s) return isNaN(n) ? null : n})parse("123") // => [123]parse("abc") // => []flatMapNullishOr
Section titled “flatMapNullishOr”Maps each element with a nullable-returning function, dropping null/undefined results.
import { Array } from "effect"
Array.flatMapNullishOr([1, 2, 3], (n) => (n % 2 === 0 ? null : n)) // => [1, 3]Pattern matching
Section titled “Pattern matching”Branches on emptiness; onNonEmpty receives the full NonEmptyReadonlyArray.
import { Array } from "effect"
const describe = Array.match({ onEmpty: () => "empty", onNonEmpty: (xs) => `${xs.length} items`})describe([]) // => "empty"describe([1, 2, 3]) // => "3 items"matchLeft
Section titled “matchLeft”Branches on emptiness, destructuring the non-empty case into (head, tail).
import { Array } from "effect"
const m = Array.matchLeft({ onEmpty: () => "empty", onNonEmpty: (head, tail) => `head: ${head}, rest: ${tail.length}`})m([1, 2, 3]) // => "head: 1, rest: 2"matchRight
Section titled “matchRight”Branches on emptiness, destructuring the non-empty case into (init, last).
import { Array } from "effect"
const m = Array.matchRight({ onEmpty: () => "empty", onNonEmpty: (init, last) => `init: ${init.length}, last: ${last}`})m([1, 2, 3]) // => "init: 2, last: 3"Do-notation
Section titled “Do-notation”The do-notation builds an array comprehension: each bind produces the cartesian product with all previous bindings (like nested loops), and filter/map add conditions and transformations.
The starting point — a single-element array of an empty scope.
import { Array, pipe } from "effect"
pipe( Array.Do, Array.bind("x", () => [1, 3, 5]), Array.bind("y", () => [2, 4, 6]), Array.filter(({ x, y }) => x < y), Array.map(({ x, y }) => [x, y] as const))// => [[1, 2], [1, 4], [1, 6], [3, 4], [3, 6], [5, 6]]Adds a named array variable to the scope, pairing each existing scope with every value the callback returns.
import { Array, pipe } from "effect"
pipe( Array.Do, Array.bind("x", () => [1, 2]), Array.bind("y", () => ["a", "b"]))// => [{ x: 1, y: "a" }, { x: 1, y: "b" }, { x: 2, y: "a" }, { x: 2, y: "b" }]Adds a computed plain value to the scope (no new array dimension, so no cartesian product).
import { Array, pipe } from "effect"
pipe( Array.Do, Array.bind("x", () => [1, 2, 3]), Array.let("doubled", ({ x }) => x * 2))// => [{ x: 1, doubled: 2 }, { x: 2, doubled: 4 }, { x: 3, doubled: 6 }]bindTo
Section titled “bindTo”Wraps each element of an existing array in an object with the given key, starting a scope. Equivalent to Array.map(self, (a) => ({ [tag]: a })).
import { Array, pipe } from "effect"
pipe([1, 2, 3], Array.bindTo("x")) // => [{ x: 1 }, { x: 2 }, { x: 3 }]Reducers
Section titled “Reducers”These produce Reducer instances that combine arrays by concatenation, for use with APIs that accept a Reducer.
getReadonlyReducerConcat
Section titled “getReadonlyReducerConcat”A Reducer that combines ReadonlyArray values by concatenation.
import { Array } from "effect"
const r = Array.getReadonlyReducerConcat<number>()r.combine([1, 2], [3, 4]) // => [1, 2, 3, 4]makeReducerConcat
Section titled “makeReducerConcat”A Reducer that combines mutable Array values by concatenation.
import { Array } from "effect"
const r = Array.makeReducerConcat<number>()r.combine([1, 2], [3, 4]) // => [1, 2, 3, 4]