[API reference](https://evolu.dev/docs/api-reference) › [@evolu/common](https://evolu.dev/docs/api-reference/common) › Array

Array helpers that help TypeScript help you.

- **Non-empty arrays**: compile-time guarantee of at least one element
- **Readonly arrays**: prevents accidental mutation

Instead of checking array length at runtime, use [NonEmptyReadonlyArray](https://evolu.dev/docs/api-reference/common/Array/type-aliases/NonEmptyReadonlyArray)
so TypeScript rejects empty arrays at compile time. Functions like
[firstInArray](https://evolu.dev/docs/api-reference/common/Array/functions/firstInArray) require a non-empty array — TypeScript won't let us pass
an empty one. [mapArray](https://evolu.dev/docs/api-reference/common/Array/functions/mapArray) preserves non-emptiness (native `map` doesn't),
while [appendToArray](https://evolu.dev/docs/api-reference/common/Array/functions/appendToArray) and [prependToArray](https://evolu.dev/docs/api-reference/common/Array/functions/prependToArray) guarantee the result is
non-empty.

All helpers return readonly arrays for safety. Consider how dangerous native
`sort()` is — it mutates the original array and returns it, making bugs hard
to track:

```ts
const sortScores = (arr: number[]) => arr.sort((a, b) => a - b);

const scores = [3, 1, 2];
const leaderboard = sortScores(scores);
leaderboard; // [1, 2, 3]
scores; // [1, 2, 3] — original order lost!
```

Imagine every method doing that.

On a `ReadonlyArray`, `.sort()` doesn't even exist. Use [sortArray](https://evolu.dev/docs/api-reference/common/Array/functions/sortArray)
instead:

```ts
const sortScores = (arr: ReadonlyArray<number>) =>
  sortArray(arr, (a, b) => a - b);

const scores: ReadonlyArray<number> = [3, 1, 2];
const leaderboard = sortScores(scores);
leaderboard; // [1, 2, 3]
scores; // [3, 1, 2] — safe!
```

Even better, require a [NonEmptyReadonlyArray](https://evolu.dev/docs/api-reference/common/Array/type-aliases/NonEmptyReadonlyArray) — there's nothing to sort
if the array is empty anyway:

```ts
const sortScores = (arr: NonEmptyReadonlyArray<number>) =>
  sortArray(arr, (a, b) => a - b);
```

Sorting an empty array isn't expensive, but functions can have side effects
like database queries or network requests. Using non-empty arrays whenever
possible is a good convention.

For performance-critical cases where mutation is needed, Evolu provides
[shiftFromArray](https://evolu.dev/docs/api-reference/common/Array/functions/shiftFromArray) and [popFromArray](https://evolu.dev/docs/api-reference/common/Array/functions/popFromArray) — but only because they improve
type safety by returning a guaranteed `T` rather than an optional value.

### When to use native methods

These helpers only exist where they add type-level value. Native methods like
`find`, `some`, `every`, `includes`, `indexOf`, and `findIndex` work well on
readonly arrays without mutation — use them directly.

## Examples

```ts
// Types - compile-time guarantee of at least one element
const _valid: NonEmptyReadonlyArray<number> = [1, 2, 3];
// ts-expect-error - empty array is not a valid NonEmptyReadonlyArray
const _invalid: NonEmptyReadonlyArray<number> = [];

// Type guards
const arr: ReadonlyArray<number> = [1, 2, 3];
if (isNonEmptyArray(arr)) {
  firstInArray(arr);
}

// Transformations
const appended = appendToArray([1, 2, 3], 4); // [1, 2, 3, 4]
const prepended = prependToArray([2, 3], 1); // [1, 2, 3]
const readonly: ReadonlyArray<number> = [1, 2, 3];
const mapped = mapArray(readonly, (x) => x * 2); // [2, 4, 6]
const filtered = filterArray(readonly, (x) => x > 1); // [2, 3]
const deduped = dedupeArray([1, 2, 1, 3, 2]); // [1, 2, 3]
const [evens, odds] = partitionArray([1, 2, 3, 4, 5], (x) => x % 2 === 0);

// Accessors
const first = firstInArray(["a", "b", "c"]); // "a"
const last = lastInArray(["a", "b", "c"]); // "c"

// Mutations
const mutable: NonEmptyArray<number> = [1, 2, 3];
shiftFromArray(mutable); // 1 (guaranteed to exist)
mutable; // [2, 3]
```

## Composition

All array helpers use a data-first style (the array is the first argument)
because it's natural for single operations:

```ts
const timestamps = mapArray(messages, (m) => m.timestamp);
```

Data-first style also reads well for a few operations, often fitting on a
line:

```ts
const cheapest = firstInArray(sortArray(prices, orderNumber));
const uniqueNames = dedupeArray(mapArray(users, (u) => u.name));
const latestDone = lastInArray(filterArray(jobs, isCompletedJob));
```

For more operations, create a function like `getOldestActiveUser` or a
generic helper.

Some libraries provide dual APIs with data-last for pipe-based composition.
Evolu prefers simplicity (in Latin, simplex means "one") so we don't have to
choose between seemingly equivalent options (Buridan's ass dilemma).

Evolu doesn't provide `pipe` because few operations compose well without it,
and for more operations, well-named functions communicate intent better.

## Types

| Name                                                                                             | Description                                                                                                                                                                                                                                                      |
| ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [NonEmptyArray](https://evolu.dev/docs/api-reference/common/Array/type-aliases/NonEmptyArray)                 | An array with at least one element.                                                                                                                                                                                                                              |
| [NonEmptyReadonlyArray](https://evolu.dev/docs/api-reference/common/Array/type-aliases/NonEmptyReadonlyArray) | A readonly array with at least one element.                                                                                                                                                                                                                      |
| [ZipArrayResult](https://evolu.dev/docs/api-reference/common/Array/type-aliases/ZipArrayResult)               | Extracts element types from a tuple of arrays, producing a tuple type.                                                                                                                                                                                           |
| [isNonEmptyArray](https://evolu.dev/docs/api-reference/common/Array/functions/isNonEmptyArray)                | Checks if an array is non-empty and narrows its type to [NonEmptyArray](https://evolu.dev/docs/api-reference/common/Array/type-aliases/NonEmptyArray) or [NonEmptyReadonlyArray](https://evolu.dev/docs/api-reference/common/Array/type-aliases/NonEmptyReadonlyArray) based on the input. |

## Constants

| Variable                                                                | Description              |
| ----------------------------------------------------------------------- | ------------------------ |
| [emptyArray](https://evolu.dev/docs/api-reference/common/Array/variables/emptyArray) | An empty readonly array. |

## Transformations

| Function                                                                        | Description                                                                                                                                                                                                                                          |
| ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [appendToArray](https://evolu.dev/docs/api-reference/common/Array/functions/appendToArray)   | Appends an item to an array, returning a new non-empty readonly array.                                                                                                                                                                               |
| [concatArrays](https://evolu.dev/docs/api-reference/common/Array/functions/concatArrays)     | Concatenates two arrays, returning a new readonly array.                                                                                                                                                                                             |
| [dedupeArray](https://evolu.dev/docs/api-reference/common/Array/functions/dedupeArray)       | Returns a new readonly array with duplicate items removed. If `by` is provided, it will be used to derive the key for uniqueness; otherwise values are used directly. Dedupes by reference equality of values (or extracted keys when `by` is used). |
| [filterArray](https://evolu.dev/docs/api-reference/common/Array/functions/filterArray)       | Filters an array using a predicate or refinement function, returning a new readonly array.                                                                                                                                                           |
| [flatMapArray](https://evolu.dev/docs/api-reference/common/Array/functions/flatMapArray)     | Maps each element to an array and flattens the result.                                                                                                                                                                                               |
| [mapArray](https://evolu.dev/docs/api-reference/common/Array/functions/mapArray)             | Maps an array using a mapper function, returning a new readonly array.                                                                                                                                                                               |
| [partitionArray](https://evolu.dev/docs/api-reference/common/Array/functions/partitionArray) | Partitions an array into two readonly arrays based on a predicate or refinement function.                                                                                                                                                            |
| [prependToArray](https://evolu.dev/docs/api-reference/common/Array/functions/prependToArray) | Prepends an item to an array, returning a new non-empty readonly array.                                                                                                                                                                              |
| [reverseArray](https://evolu.dev/docs/api-reference/common/Array/functions/reverseArray)     | Returns a new reversed readonly array.                                                                                                                                                                                                               |
| [sortArray](https://evolu.dev/docs/api-reference/common/Array/functions/sortArray)           | Returns a new sorted readonly array.                                                                                                                                                                                                                 |
| [spliceArray](https://evolu.dev/docs/api-reference/common/Array/functions/spliceArray)       | Returns a new readonly array with elements removed and/or replaced.                                                                                                                                                                                  |
| [zipArray](https://evolu.dev/docs/api-reference/common/Array/functions/zipArray)             | Combines multiple arrays into an array of tuples.                                                                                                                                                                                                    |

## Accessors

| Function                                                                    | Description                                     |
| --------------------------------------------------------------------------- | ----------------------------------------------- |
| [firstInArray](https://evolu.dev/docs/api-reference/common/Array/functions/firstInArray) | Returns the first element of a non-empty array. |
| [lastInArray](https://evolu.dev/docs/api-reference/common/Array/functions/lastInArray)   | Returns the last element of a non-empty array.  |

## Mutations

| Function                                                                        | Description                                                                    |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| [popFromArray](https://evolu.dev/docs/api-reference/common/Array/functions/popFromArray)     | Pops (removes and returns) the last element from a non-empty mutable array.    |
| [shiftFromArray](https://evolu.dev/docs/api-reference/common/Array/functions/shiftFromArray) | Shifts (removes and returns) the first element from a non-empty mutable array. |

## Constructors

| Function                                                                        | Description               |
| ------------------------------------------------------------------------------- | ------------------------- |
| [arrayFrom](https://evolu.dev/docs/api-reference/common/Array/functions/arrayFrom)           | Better `Array.from`.      |
| [arrayFromAsync](https://evolu.dev/docs/api-reference/common/Array/functions/arrayFromAsync) | Better `Array.fromAsync`. |