[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);
expect(leaderboard).toEqual([1, 2, 3]);
expect(scores).toEqual([1, 2, 3]);
expect(leaderboard).toBe(scores);
```

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);
expect(leaderboard).toEqual([1, 2, 3]);
expect(scores).toEqual([3, 1, 2]);
expect(leaderboard).not.toBe(scores);
```

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);

const leaderboard = sortScores([3, 1, 2]);
expect(leaderboard).toEqual([1, 2, 3]);
expectTypeOf(leaderboard).toEqualTypeOf<NonEmptyReadonlyArray<number>>();
```

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.

### 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.

```ts

const valid: NonEmptyReadonlyArray<number> = [1, 2, 3];
// @ts-expect-error An empty array is not non-empty.
const invalid: NonEmptyReadonlyArray<number> = [];

expect(valid.find((value) => value === 2)).toBe(2);
```

## Composition

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

```ts

interface Message {
  readonly timestamp: number;
}

const messages: ReadonlyArray<Message> = [{ timestamp: 10 }, { timestamp: 20 }];
const timestamps = mapArray(messages, (m) => m.timestamp);
expect(timestamps).toEqual([10, 20]);
```

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

```ts
import {
  dedupeArray,
  filterArray,
  firstInArray,
  isNonEmptyArray,
  lastInArray,
  mapArray,
  orderNumber,
  sortArray,
} from "@evolu/common";

const cheapest = firstInArray(sortArray([30, 10, 20], orderNumber));
expect(cheapest).toBe(10);

const users = [{ name: "Ada" }, { name: "Linus" }, { name: "Ada" }];
const uniqueNames = dedupeArray(mapArray(users, (u) => u.name));
expect(uniqueNames).toEqual(["Ada", "Linus"]);

const jobs = [
  { id: 1, done: false },
  { id: 2, done: true },
];
const completedJobs = filterArray(jobs, (job) => job.done);
if (!isNonEmptyArray(completedJobs)) throw new Error("Expected a job");
const latestDone = lastInArray(completedJobs);

expect(latestDone).toEqual({ id: 2, done: true });
```

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                                                                                                                                                                                                                                                      |
| ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [AtLeastTwoReadonlyArray](https://evolu.dev/docs/api-reference/common/Array/type-aliases/AtLeastTwoReadonlyArray) | A readonly array with at least two elements.                                                                                                                                                                                                                     |
| [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. |

## 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`.                                 |
| [createMutableArray](https://evolu.dev/docs/api-reference/common/Array/functions/createMutableArray) | Creates a mutable sparse Array with the specified length. |

## 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. Items are compared using `Set` equality (SameValueZero): primitives by value, and objects and arrays by reference. If `by` is provided, it derives the comparison key. |
| [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.  |