npm package: @r01al/array-polyfills
Description: Cool JS Array Polyfills
Author: Roi Tal
Latest version: 1.0.10

# Cool Array Polyfills

✨ A tiny TypeScript library that adds useful array utilities in two ways:

- 🧩 Side-effectful `Array.prototype` polyfills (opt-in via the `auto` entry).
- 🧰 Standalone helper functions for use without touching prototypes.

## Benefits

- 🌍 Works in both modern bundlers and simple `<script>` tags (UMD builds).
- 🧭 Lets you choose between prototype methods or pure functions.
- ✅ Strong typing for safer use in TypeScript.
- 🍃 Small, focused helpers that are easy to tree‑shake.

## Install

```bash
npm i @r01al/array-polyfills
```

## Quick start

### Standalone helpers (no prototype changes)

```ts
import {
  first,
  last,
  unique,
  chunk,
  compact,
  compactMap,
  random,
  keyValueMap,
  sum,
  avg,
  max,
  min,
  shuffle,
  groupBy,
  flatten,
  zip,
  partition,
  pluck,
  countBy,
  difference,
  intersection,
  union,
  uniqBy,
  sortBy,
  sample,
  pad
} from "@r01al/array-polyfills";

first([1, 2, 3]);
unique([1, 1, 2]);
chunk([1, 2, 3, 4], 2);
compact([0, 1, "", 2]);
compactMap([1, 2, 3], n => (n > 1 ? n * 2 : null));
groupBy([{ type: "a" }, { type: "b" }], "type");
flatten([1, [2, 3], 4]);
zip([1, 2], ["a", "b"]);
partition([1, 2, 3, 4], n => n % 2 === 0);
pluck([{ id: 1 }, { id: 2 }], "id");
countBy(["a", "b", "a"], value => value);
difference([1, 2, 3], [2, 4]);
intersection([1, 2, 3], [2, 3, 4]);
union([1, 2], [2, 3], [3, 4]);
uniqBy([{ id: 1 }, { id: 1 }, { id: 2 }], "id");
sortBy([{ n: 2 }, { n: 1 }], "n");
sample([1, 2, 3, 4], 2);
pad([1, 2], 5, 0);
```

### Polyfill `Array.prototype`

```ts
import "@r01al/array-polyfills/auto";

[1, 2, 3].first();
[1, 1, 2].unique();
[1, 2, 3, 4].chunk(2);
[0, 1, "", 2].compact();
([1, 2, 3] as number[]).compactMap(n => (n > 1 ? n * 2 : null));
[{ type: "a" }, { type: "b" }].groupBy("type");
([1, [2, 3], 4] as (number | number[])[]).flatten();
[1, 2].zip(["a", "b"]);
[1, 2, 3, 4].partition(n => n % 2 === 0);
([{ id: 1 }, { id: 2 }] as { id: number }[]).pluck("id");
["a", "b", "a"].countBy(value => value);
[1, 2, 3].difference([2, 4]);
[1, 2, 3].intersection([2, 3, 4]);
[1, 2].union([2, 3], [3, 4]);
([{ id: 1 }, { id: 1 }, { id: 2 }] as { id: number }[]).uniqBy("id");
([{ n: 2 }, { n: 1 }] as { n: number }[]).sortBy("n");
[1, 2, 3, 4].sample(2);
[1, 2].pad(5, 0);
```

### Browser (UMD via unpkg)

Auto polyfills (no module loader required):

```html
<script src="https://unpkg.com/@r01al/array-polyfills@latest/dist/auto.umd.js"></script>
<script>
  [1, 2, 3].first();
  [1, 1, 2].unique();
</script>
```

Standalone helpers (global `ArrayPolyfills`):

```html
<script src="https://unpkg.com/@r01al/array-polyfills@latest/dist/index.umd.js"></script>
<script>
  ArrayPolyfills.first([1, 2, 3]);
  ArrayPolyfills.shuffle([1, 2, 3]);
</script>
```

Note: UMD bundles are ES5-targeted, but older browsers may still require `Map`/`Set` polyfills.

## API

All functions below can be used either as standalone helpers or as prototype methods when using the `auto` entry.

### first

```ts
first<T>(arr: T[]): T | undefined
```

Returns the first element, or `undefined` if the array is empty.

### last

```ts
last<T>(arr: T[]): T | undefined
```

Returns the last element, or `undefined` if the array is empty.

### unique

```ts
unique<T>(arr: T[]): T[]
```

Returns a new array with unique elements. Primitives are de-duplicated by value; objects use a deep equality check.

### chunk

```ts
chunk<T>(arr: T[], size: number): T[][]
```

Splits the array into chunks of `size`. Throws if `size` is not a positive integer.

### compact

```ts
compact<T>(arr: T[]): T[]
```

Returns a new array with all falsy values removed (`false`, `0`, `""`, `null`, `undefined`).

Example:

```ts
compact([0, 1, "", 2, null, undefined, false, 3]);
// [1, 2, 3]
```

### compactMap

```ts
compactMap<T, R>(
  arr: T[],
  mapper: (value: T, index: number, arr: T[]) => R
): Exclude<R, null | undefined>[]
```

Maps items and removes `null`/`undefined` results.

Example:

```ts
compactMap([1, 2, 3], n => (n > 1 ? n * 2 : null));
// [4, 6]
```

### random

```ts
random<T>(arr: T[]): T | undefined
```

Returns a random element, or `undefined` if the array is empty.

### keyValueMap

```ts
keyValueMap<T extends Record<string, any>>(arr: T[], key: string, value: string): Record<string, any>
```

Builds an object mapping `item[key]` to `item[value]`. Throws if `key` or `value` is missing, any element is falsy, non-object, or missing `key`.

Example:

```ts
keyValueMap(
  [
    { id: "a", name: "Alpha" },
    { id: "b", name: "Beta" }
  ],
  "id",
  "name"
);
// { a: "Alpha", b: "Beta" }
```

### groupBy

```ts
groupBy<T, K extends PropertyKey>(
  arr: T[],
  key: ((item: T, index: number, arr: T[]) => K) | keyof T
): Record<K, T[]>
```

Groups items by a property name or mapper function.

Example:

```ts
groupBy(
  [
    { type: "a", value: 1 },
    { type: "b", value: 2 },
    { type: "a", value: 3 }
  ],
  "type"
);
// { a: [{...}, {...}], b: [{...}] }
```

### pluck

```ts
pluck<T, K extends keyof T>(arr: T[], key: K): T[K][]
```

Plucks a property value from each item.

Example:

```ts
pluck([{ id: 1 }, { id: 2 }], "id");
// [1, 2]
```

### countBy

```ts
countBy<T, K extends PropertyKey>(
  arr: T[],
  key: ((item: T, index: number, arr: T[]) => K) | keyof T
): Record<K, number>
```

Counts items by a property name or mapper function.

Example:

```ts
countBy(["a", "b", "a"], value => value);
// { a: 2, b: 1 }
```

### sum

```ts
sum(arr: number[]): number
```

Returns the sum of all numbers. Throws if any element is not a number. Returns `0` for an empty array.

### avg

```ts
avg(arr: number[]): number | undefined
```

Returns the average. Throws if any element is not a number. Returns `undefined` for an empty array.

### max

```ts
max(arr: number[]): number | undefined
```

Returns the maximum value. Throws if any element is not a number. Returns `undefined` for an empty array.

### min

```ts
min(arr: number[]): number | undefined
```

Returns the minimum value. Throws if any element is not a number. Returns `undefined` for an empty array.

### shuffle

```ts
shuffle<T>(arr: T[]): T[]
```

Shuffles the array in place and returns the same array reference.

### flatten

```ts
flatten<T>(arr: (T | T[])[]): T[]
```

Flattens the array by one level.

Example:

```ts
flatten([1, [2, 3], 4]);
// [1, 2, 3, 4]
```

### zip

```ts
zip<T>(arr: T[], ...arrays: any[][]): any[][]
```

Zips arrays into tuples, truncated to the shortest array length. If no extra arrays are provided, returns single-item tuples.

Example:

```ts
zip([1, 2, 3], ["a", "b"]);
// [[1, "a"], [2, "b"]]
```

### partition

```ts
partition<T>(
  arr: T[],
  predicate: (value: T, index: number, arr: T[]) => boolean
): [T[], T[]]
```

Splits items into two arrays: those that pass the predicate and those that fail.

Example:

```ts
partition([1, 2, 3, 4], n => n % 2 === 0);
// [[2, 4], [1, 3]]
```

### difference

```ts
difference<T>(arr: T[], ...arrays: T[][]): T[]
```

Returns items that are not present in the other arrays.

Example:

```ts
difference([1, 2, 3], [2, 4]);
// [1, 3]
```

### intersection

```ts
intersection<T>(arr: T[], ...arrays: T[][]): T[]
```

Returns items present in all arrays.

Example:

```ts
intersection([1, 2, 3], [2, 3, 4]);
// [2, 3]
```

### union

```ts
union<T>(arr: T[], ...arrays: T[][]): T[]
```

Returns a unique merge of the array and the other arrays.

Example:

```ts
union([1, 2], [2, 3], [3, 4]);
// [1, 2, 3, 4]
```

### uniqBy

```ts
uniqBy<T, K>(
  arr: T[],
  key: ((item: T, index: number, arr: T[]) => K) | keyof T
): T[]
```

Returns the first item for each unique key.

Example:

```ts
uniqBy([{ id: 1 }, { id: 1 }, { id: 2 }], "id");
// [{ id: 1 }, { id: 2 }]
```

### sortBy

```ts
sortBy<T, K extends string | number | bigint>(
  arr: T[],
  key: ((item: T, index: number, arr: T[]) => K) | keyof T
): T[]
```

Returns a new array sorted by the key (stable). For dates, map to `getTime()` in the mapper.

Example:

```ts
sortBy([{ n: 2 }, { n: 1 }], "n");
// [{ n: 1 }, { n: 2 }]
```

### sample

```ts
sample<T>(arr: T[], count: number): T[]
```

Returns a random sample without replacement.

Example:

```ts
sample([1, 2, 3, 4], 2);
// length 2
```

### pad

```ts
pad<T>(arr: T[], length: number, value: T): T[]
```

Pads the array to the given length with the provided value.

Example:

```ts
pad([1, 2], 5, 0);
// [1, 2, 0, 0, 0]
```

## Notes

- The `auto` entry defines methods only if they do not already exist.
- The `auto` entry is side-effectful by design and is listed under `sideEffects` for bundlers.
- Build outputs live under `dist/` for ESM, CJS, and UMD.