npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

swiss-ak

v3.4.2

Published

A collection of useful little things that I like to reuse across projects

Downloads

684

Readme

swiss-ak (Swiss Army Knife)

A collection of useful little things that I like to reuse across projects

times

A collection of Tools for calculating simple times. Each unit (e.g. second) has: a type (second), a constant (SECOND) and a function for getting multiples (seconds(x: second) => ms)

| unit | type | constant | function | | ----------- | ------------ | ------------- | ---------------------------------- | | millisecond | ms | MILLISECOND | milliseconds(x: ms) => ms | | second | second | SECOND | seconds(x: second) => ms | | minute | minute | MINUTE | minutes(x: minute) => ms | | hour | hour | HOUR | hours(x: hour) => ms | | day | day | DAY | days(x: day) => ms | | week | week | WEEK | weeks(x: week) => ms | | month | month | MONTH | months(x: month) => ms | | year | year | YEAR | years(x: year) => ms | | decade | decade | DECADE | decades(x: decade) => ms | | century | century | CENTURY | centuries(x: century) => ms | | millennium | millennium | MILLENNIUM | millenniums(x: millennium) => ms |

waiters

Async functions that return promises at or after a given time.

'Accurate/pinged' waiters ping at intermediary points to resolve at a more accurate time.

| Name | Description | Example | | --------- | ---------------------------------------------------- | ----------------------------------------------- | | wait | Standard wait promise (using setTimeout) | minutes(2) = in 2 minutes | | waitFor | Accurate (pinged) wait the given ms | minutes(2) = in 2 minutes | | waitUntil | Accurate (pinged) wait until given time | Date.now() + minutes(2) = in 2 minutes | | waitEvery | Accurate (pinged) wait for next 'every X' event | hours(1) = next full hour (e.g. 17:00, 22:00) | | interval | Accurate (pinged) interval for every 'every X' event | hours(1) = every hour, on the hour |

wait

wait(time: ms): Promise<unknown>
waiters.wait(time: ms): Promise<unknown>

Standard wait promise (using setTimeout)

import { wait } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
await wait(minutes(2));
console.log(new Date().toTimeString()); // 12:32:10

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:-----------------------------| | 0 | time | Yes | ms | Time to wait in milliseconds |

| Return Type | | |--------------------|--------------------------------------------| | Promise<unknown> | Promise that resolves after the given time |

waitUntil

waitUntil(time: ms): Promise<null>
waiters.waitUntil(time: ms): Promise<null>

Accurate (pinged) wait until given time

import { waitUntil } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
await waitUntil(Date.now() + minutes(10));
console.log(new Date().toTimeString()); // 12:40:10

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:------------------------| | 0 | time | Yes | ms | Unix time to wait until |

| Return Type | | |-----------------|-----------------------------------------| | Promise<null> | Promise that resolves at the given time |

waitFor

waitFor(time: ms): Promise<null>
waiters.waitFor(time: ms): Promise<null>

Accurate (pinged) wait the given ms

import { waitFor } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
await waitFor(minutes(5));
console.log(new Date().toTimeString()); // 12:35:10

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:-----------------------------| | 0 | time | Yes | ms | Time to wait in milliseconds |

| Return Type | | |-----------------|--------------------------------------------| | Promise<null> | Promise that resolves after the given time |

waitEvery

waitEvery(timing: ms, offset: ms): Promise<null>
waiters.waitEvery(timing: ms, offset: ms): Promise<null>

Accurate (pinged) wait for next 'every X' event

import { waitEvery } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
await waitEvery(hours(2));
console.log(new Date().toTimeString()); // 14:00:00

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:------------------------------| | 0 | timing | Yes | ms | Timing period in milliseconds | | 1 | offset | No | ms | Offset in milliseconds |

| Return Type | | |-----------------|---------------------------------------------------| | Promise<null> | Promise that resolves at the next 'every X' event |

stopInterval

stopInterval(intID: number): void
waiters.stopInterval(intID: number): void
import { interval, stopInterval } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
interval((intID, count) => {
  console.log(new Date().toTimeString()); // 13:00:00, 14:00:00, 15:00:00
  if (count === 3) {
    stopInterval(intID);
  }
}, hours(1));

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------|:------------| | 0 | intID | Yes | number | Interval ID |

| Return Type | |-------------| | void |

interval

interval(action: (intID?: number, count?: number) => any, timing: ms): number
waiters.interval(action: (intID?: number, count?: number) => any, timing: ms): number

Accurate (pinged) interval for every 'every X' event

import { interval, stopInterval } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
interval((intID, count) => {
  console.log(new Date().toTimeString()); // 13:00:00, 14:00:00, 15:00:00
  if (count === 3) {
    stopInterval(intID);
  }
}, hours(1));

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:------------------------------------------|:-------------------------------| | 0 | action | Yes | (intID?: number, count?: number) => any | Action to run on each interval | | 1 | timing | Yes | ms | Timing period in milliseconds |

| Return Type | | |-------------|-------------| | number | Interval ID |

fn

A collection of useful higher-order functions.

noop

fn.noop(): void

No operation. Do nothing, return nothing.

const run = condition ? doSomething : fn.noop;
run();

| Return Type | |-------------| | void |

noact

fn.noact(item: T): T

No action. Returns the first argument it receives.

const items = stuff
  .map(condition ? mapSomething : fn.noact)

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:---------------| | 0 | item | No | T | Item to return |

| Return Type | | |-------------|--------------------------------| | T | The first argument it receives |

result

fn.result(item: T): () => T

Returns a function that returns the first argument.

const items = stuff
  .filter(condition ? mapSomething : fn.result(true))

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:---------------------------------| | 0 | item | No | T | Item to return from the function |

| Return Type | | |-------------|------------------------------------------| | () => T | Function that returns the first argument |

resolve

fn.resolve(item: T): () => Promise<T>

Returns an async function that resolves to the first argument

Like fn.result, but wrapped in a Promise

await Promise.all(stuff.map(fn.resolve()));

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:----------------| | 0 | item | No | T | Item to resolve |

| Return Type | | |--------------------|---------------------------------------------------------------------| | () => Promise<T> | Function that returns a Promise that resolves to the first argument |

reject

fn.reject(item: T): () => Promise<T>

Returns an async function that rejects with the first argument

await Promise.all(stuff.map(fn.reject()));

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:---------------| | 0 | item | No | T | Item to reject |

| Return Type | | |--------------------|----------------------------------------------------------------------| | () => Promise<T> | Function that returns a Promise that rejects with the first argument |

filters

fn.filters;

Collection of functions that can be used with Array.filter

exists

fn.exists(item: T): boolean
fn.filters.exists(item: T): boolean
filters.exists(item: T): boolean

Returns true if item isn't null or undefined.

[null, 1, undefined, 2].filter(fn.exists); // [1, 2]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:---------------------------| | 0 | item | Yes | T | Item to check if it exists |

| Return Type | | |-------------|--------------------------------------| | boolean | True if item isn't null or undefined |

isTruthy

fn.isTruthy(item: T): boolean
fn.filters.isTruthy(item: T): boolean
filters.isTruthy(item: T): boolean

Returns true if item is truthy.

[0, 1, 2].filter(fn.isTruthy); // [1, 2]
['', 'a', 'b'].filter(fn.isTruthy); // ['a', 'b']

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:------------------------------| | 0 | item | Yes | T | Item to check if it is truthy |

| Return Type | | |-------------|------------------------| | boolean | True if item is truthy |

isFalsy

fn.isFalsy(item: T): boolean
fn.filters.isFalsy(item: T): boolean
filters.isFalsy(item: T): boolean

Returns true if item is falsy.

[0, 1, 2].filter(fn.isFalsy); // [0]
['', 'a', 'b'].filter(fn.isFalsy); // ['']

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:-----------------------------| | 0 | item | Yes | T | Item to check if it is falsy |

| Return Type | | |-------------|-----------------------| | boolean | True if item is falsy |

isEmpty

fn.isEmpty(item: T[] | string): boolean
fn.filters.isEmpty(item: T[] | string): boolean
filters.isEmpty(item: T[] | string): boolean

Returns true if item's length is 0

['', 'a', 'b'].filter(fn.isEmpty); // ['']
[[], [1], [2]].filter(fn.isEmpty); // [[]]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:----------------|:-----------------------------| | 0 | item | Yes | T[] \| string | Item to check if it is empty |

| Return Type | | |-------------|----------------------------| | boolean | True if item's length is 0 |

isNotEmpty

fn.isNotEmpty(item: T[] | string): boolean
fn.filters.isNotEmpty(item: T[] | string): boolean
filters.isNotEmpty(item: T[] | string): boolean

Returns true if item's length is 1 or more

['', 'a', 'b'].filter(fn.isNotEmpty); // ['a', 'b']
[[], [1], [2]].filter(fn.isNotEmpty); // [[1], [2]]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:----------------|:---------------------------------| | 0 | item | Yes | T[] \| string | Item to check if it is not empty |

| Return Type | | |-------------|------------------------------------| | boolean | True if item's length is 1 or more |

isEqual

fn.isEqual(item: T): (other: T) => boolean
fn.filters.isEqual(item: T): (other: T) => boolean
filters.isEqual(item: T): (other: T) => boolean

Returns a function that returns true if the item is equal to provided value.

[0, 1, 2].filter(fn.isEqual(1)); // [1]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:---------------------------------------------------------| | 0 | item | Yes | T | Item to check whether each item of the array is equal to |

| Return Type | | |-------------------------|---------------------------------| | (other: T) => boolean | Function to use in Array.filter |

isNotEqual

fn.isNotEqual(item: T): (other: T) => boolean
fn.filters.isNotEqual(item: T): (other: T) => boolean
filters.isNotEqual(item: T): (other: T) => boolean

Returns a function that returns true if the item is not equal to provided value.

[0, 1, 2].filter(fn.isNotEqual(1)); // [0, 2]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:-------------------------------------------------------------| | 0 | item | Yes | T | Item to check whether each item of the array is not equal to |

| Return Type | | |-------------------------|---------------------------------| | (other: T) => boolean | Function to use in Array.filter |

dedupe

fn.dedupe(item: T, index: number, array: T[]): boolean
fn.filters.dedupe(item: T, index: number, array: T[]): boolean
filters.dedupe(item: T, index: number, array: T[]): boolean

Removes duplicate items from an array.

[0, 1, 2, 1, 0].filter(fn.dedupe); // [0, 1, 2]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------|:------------------------| | 0 | item | Yes | T | Given item in array | | 1 | index | Yes | number | Index of the given item | | 2 | array | Yes | T[] | Array of items |

| Return Type | | |-------------|-------------------------------------------------------| | boolean | True if the item is the first occurrence in the array |

dedupeMapped

fn.dedupeMapped(mapFn: (value?: T, index?: number, array?: T[]) => U): (item: T, index: number, array: T[]) => boolean
fn.filters.dedupeMapped(mapFn: (value?: T, index?: number, array?: T[]) => U): (item: T, index: number, array: T[]) => boolean
filters.dedupeMapped(mapFn: (value?: T, index?: number, array?: T[]) => U): (item: T, index: number, array: T[]) => boolean

Removes duplicate items from an array based on a mapped value.

[2, 4, 6, 8, 10, 12].filter(fn.dedupeMapped((v) => v % 3)); // [ 2, 4, 6 ] (maps to [ 2, 1, 0, 2, 1, 0 ])

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:------------------------------------------------|:-------------------------------------------------------------------------------| | 0 | mapFn | Yes | (value?: T, index?: number, array?: T[]) => U | Function to map the item to a new value (will be used to check for duplicates) |

| Return Type | | |---------------------------------------------------|---------------------------------| | (item: T, index: number, array: T[]) => boolean | Function to use in Array.filter |

maps

fn.maps;

Collection of functions that can be used with Array.map

toString

fn.toString(item: T): string
fn.maps.toString(item: T): string
maps.toString(item: T): string

Maps the item to a string.

[0, 1, 2].map(fn.toString); // ['0', '1', '2']

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:-----------------| | 0 | item | Yes | T | Item in an array |

| Return Type | | |-------------|--------------------| | string | String of the item |

toNumber

fn.toNumber(item: T): number
fn.maps.toNumber(item: T): number
maps.toNumber(item: T): number

Maps the item to a number.

['0', '1', '2'].map(fn.toNumber); // [0, 1, 2]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:-----------------| | 0 | item | Yes | T | Item in an array |

| Return Type | | |-------------|--------------------| | number | Number of the item |

toBool

fn.toBool(item: T): boolean
fn.maps.toBool(item: T): boolean
maps.toBool(item: T): boolean

Maps the item to a boolean.

[0, 1, 2].map(fn.toBool); // [false, true, true]
['true', 'false', '', 'text'].map(fn.toBool); // [true, false, false, true]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:-----------------| | 0 | item | Yes | T | Item in an array |

| Return Type | | |-------------|---------------------| | boolean | Boolean of the item |

toProp

fn.toProp(propName: keyof O): (item: O) => O[keyof O]
fn.maps.toProp(propName: keyof O): (item: O) => O[keyof O]
maps.toProp(propName: keyof O): (item: O) => O[keyof O]

Maps the item to a given property of the item

[{name: 'Jack'}, {name: 'Jill'}].map(fn.toProp('name')); // ['Jack', 'Jill']

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:----------|:-------------------------------| | 0 | propName | Yes | keyof O | Property to get from each item |

| Return Type | | |---------------------------|------------------------------| | (item: O) => O[keyof O] | Function to use in Array.map |

toFixed

fn.toFixed(precision: number): (num: number) => number
fn.maps.toFixed(precision: number): (num: number) => number
maps.toFixed(precision: number): (num: number) => number

Map the items (numbers) of an array to a fixed precision.

[1.234, 5.678, 9.012].map(fn.toFixed(2)); // [1.23, 5.68, 9.01]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------|:-------------------------------------| | 0 | precision | Yes | number | Number of decimal places to round to |

| Return Type | | |---------------------------|------------------------------| | (num: number) => number | Function to use in Array.map |

sorts

fn.sorts;

Collection of functions that can be used with Array.sort

asc

fn.asc(a: T, b: T): number
fn.sorts.asc(a: T, b: T): number
sorts.asc(a: T, b: T): number

Sort ascending.

[2, 4, 3, 1].sort(fn.asc); // [1, 2, 3, 4]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:----------------| | 0 | a | Yes | T | Item to compare | | 1 | b | Yes | T | Item to compare |

| Return Type | | |-------------|-------------------------| | number | Number used for sorting |

desc

fn.desc(a: T, b: T): number
fn.sorts.desc(a: T, b: T): number
sorts.desc(a: T, b: T): number

Sort descending.

[2, 4, 3, 1].sort(fn.desc); // [4, 3, 2, 1]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:----------------| | 0 | a | Yes | T | Item to compare | | 1 | b | Yes | T | Item to compare |

| Return Type | | |-------------|-------------------------| | number | Number used for sorting |

byProp

fn.byProp(propName: keyof O, sortFn: SortFn<O[keyof O]>): SortFn<O>
fn.sorts.byProp(propName: keyof O, sortFn: SortFn<O[keyof O]>): SortFn<O>
sorts.byProp(propName: keyof O, sortFn: SortFn<O[keyof O]>): SortFn<O>

Sort by a given property.

const people = [{age: 2}, {age: 4}, {age: 3}, {age: 1}];
people.sort(fn.byProp('age', fn.asc)); // [{age: 1}, {age: 2}, {age: 3}, {age: 4}]

| # | Parameter Name | Required | Type | Default | Description | |:---:|:---------------|:---------|:---------------------|:---------------|:---------------------| | 0 | propName | Yes | keyof O | | Property to sort by | | 1 | sortFn | No | SortFn<O[keyof O]> | fn.sorts.asc | Sort function to use |

| Return Type | | |-------------|-------------------------------| | SortFn<O> | Function to use in Array.sort |

nearestTo

fn.nearestTo(target: number | `${number}`): (a: number | `${number}`, b: number | `${number}`) => number
fn.sorts.nearestTo(target: number | `${number}`): (a: number | `${number}`, b: number | `${number}`) => number
sorts.nearestTo(target: number | `${number}`): (a: number | `${number}`, b: number | `${number}`) => number

Sort by the nearest value to the given value.

Values get converted to numbers before comparison.

const people = [2, 4, 3, 1];
people.sort(fn.nearestTo(3)); // [3, 2, 4, 1]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------------------------|:------------------------| | 0 | target | Yes | number \| `${number}` | Target value to sort by |

| Return Type | | |--------------------------------------------------------------------|-------------------------------| | (a: number \| `${number}`, b: number \| `${number}`) => number | Function to use in Array.sort |

furthestFrom

fn.furthestFrom(target: number | `${number}`): (a: number | `${number}`, b: number | `${number}`) => number
fn.sorts.furthestFrom(target: number | `${number}`): (a: number | `${number}`, b: number | `${number}`) => number
sorts.furthestFrom(target: number | `${number}`): (a: number | `${number}`, b: number | `${number}`) => number

Sort by the furthest value to the given value.

const people = [2, 4, 3, 1];
people.sort(fn.furthestFrom(3)); // [1, 2, 4, 3]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------------------------|:------------------------| | 0 | target | Yes | number \| `${number}` | Target value to sort by |

| Return Type | | |--------------------------------------------------------------------|-------------------------------| | (a: number \| `${number}`, b: number \| `${number}`) => number | Function to use in Array.sort |

array

fn.array(sortFn: SortFn<T>): (a: T[], b: T[]) => number
fn.sorts.array(sortFn: SortFn<T>): (a: T[], b: T[]) => number
sorts.array(sortFn: SortFn<T>): (a: T[], b: T[]) => number

Sort an array of arrays by the given sort function.

Sorts by the first item in the array, then the second, etc. until a non-zero result is found.

const arr = [[1, 2], [3, 4], [5, 6]];
arr.sort(fn.array(fn.asc)); // [[1, 2], [3, 4], [5, 6]]

| # | Parameter Name | Required | Type | Default | Description | |:---:|:---------------|:---------|:------------|:---------------|:---------------------| | 0 | sortFn | No | SortFn<T> | fn.sorts.asc | Sort function to use |

| Return Type | | |------------------------------|-------------------------------| | (a: T[], b: T[]) => number | Function to use in Array.sort |

arrayAsc

fn.arrayAsc(a: T, b: T): number
fn.sorts.arrayAsc(a: T, b: T): number
sorts.arrayAsc(a: T, b: T): number

Sort an array of arrays in ascending order

Sorts by the first item in the array, then the second, etc. until a non-zero result is found.

const arr = [[1, 2], [3, 4], [5, 6]];
arr.sort(fn.arrayAsc); // [[1, 2], [3, 4], [5, 6]]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:----------------| | 0 | a | Yes | T | Item to compare | | 1 | b | Yes | T | Item to compare |

| Return Type | | |-------------|-------------------------| | number | Number used for sorting |

arrayDesc

fn.arrayDesc(a: T, b: T): number
fn.sorts.arrayDesc(a: T, b: T): number
sorts.arrayDesc(a: T, b: T): number

Sort an array of arrays in descending order

Sorts by the first item in the array, then the second, etc. until a non-zero result is found.

const arr = [[1, 2], [3, 4], [5, 6]];
arr.sort(fn.arrayDesc); // [[5, 6], [3, 4], [1, 2]]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:----------------| | 0 | a | Yes | T | Item to compare | | 1 | b | Yes | T | Item to compare |

| Return Type | | |-------------|-------------------------| | number | Number used for sorting |

reduces

fn.reduces;

Collection of functions that can be used with Array.reduce

combine

fn.combine(a: T, b: T): T
fn.reduces.combine(a: T, b: T): T
reduces.combine(a: T, b: T): T

Adds or concats the items

[1, 2, 3].reduce(fn.combine); // 6
['a', 'b', 'c'].reduce(fn.combine); // 'abc'

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:-----|:----------------| | 0 | a | Yes | T | Item to combine | | 1 | b | Yes | T | Item to combine |

| Return Type | | |-------------|---------------| | T | Combined item |

combineProp

fn.combineProp(propName: keyof O): (a: O[keyof O], b: O) => O[keyof O]
fn.reduces.combineProp(propName: keyof O): (a: O[keyof O], b: O) => O[keyof O]
reduces.combineProp(propName: keyof O): (a: O[keyof O], b: O) => O[keyof O]

Adds or concats the given property of the items

Note: The initial value is required, because the first item is not yet an object.

const people = [{name: 'a', age: 1}, {name: 'b', age: 2}, {name: 'c', age: 3}];
people.reduce(fn.combineProp('age'), 0); // 6
people.reduce(fn.combineProp('name'), ''); // 'abc'

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:----------|:--------------------| | 0 | propName | Yes | keyof O | Property to combine |

| Return Type | | |---------------------------------------|---------------------------------| | (a: O[keyof O], b: O) => O[keyof O] | Function to use in Array.reduce |

mode

fn.mode(prev: T, curr: T, index: number, arr: T[]): T
fn.reduces.mode(prev: T, curr: T, index: number, arr: T[]): T
reduces.mode(prev: T, curr: T, index: number, arr: T[]): T

Returns the most common value in an array.

[1, 2, 3, 2, 1, 1].reduce(fn.mode); // 1

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------|:---------------------------| | 0 | prev | Yes | T | Previous value | | 1 | curr | Yes | T | Current value | | 2 | index | Yes | number | Index of the current value | | 3 | arr | Yes | T[] | Array of values |

| Return Type | | |-------------|--------------------------| | T | Most common value so far |

modeMapped

fn.modeMapped(mapFn: (value: T, index: number, array: T[]) => U): (prev: T, curr: T, index: number, arr: T[]) => T
fn.reduces.modeMapped(mapFn: (value: T, index: number, array: T[]) => U): (prev: T, curr: T, index: number, arr: T[]) => T
reduces.modeMapped(mapFn: (value: T, index: number, array: T[]) => U): (prev: T, curr: T, index: number, arr: T[]) => T

Returns the most common value in an array, based on a given map function.

[2, 4, 6, 8, 9, 12].reduce(fn.modeMapped((v) => v % 3)); // 6 (maps to [ 2, 1, 0, 2, 0, 0 ])

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------------------------------------------|:--------------------| | 0 | mapFn | Yes | (value: T, index: number, array: T[]) => U | Map function to use |

| Return Type | | |----------------------------------------------------|---------------------------------| | (prev: T, curr: T, index: number, arr: T[]) => T | Function to use in Array.reduce |

everys

fn.everys;

Collection of functions that can be used with Array.every

isAllEqual

fn.isAllEqual(val: T, i: number, arr: T[]): boolean
fn.everys.isAllEqual(val: T, i: number, arr: T[]): boolean
everys.isAllEqual(val: T, i: number, arr: T[]): boolean

Returns if all the items are equal to one another.

[1, 1, 1].every(fn.isAllEqual); // true
[1, 2, 1].every(fn.isAllEqual); // false

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------|:-------------------| | 0 | val | Yes | T | Value to check | | 1 | i | Yes | number | Index of the value | | 2 | arr | Yes | T[] | Array of values |

| Return Type | | |-------------|-------------------------------------------------------| | boolean | True if all the items are equal to one another so far |

isUnique

fn.isUnique(val: T, i: number, arr: T[]): boolean
fn.everys.isUnique(val: T, i: number, arr: T[]): boolean
everys.isUnique(val: T, i: number, arr: T[]): boolean

Returns true if the item is unique in the array.

[1, 1, 1].every(fn.isUnique); // false
[1, 2, 1].every(fn.isUnique); // false
[1, 2, 3].every(fn.isUnique); // true

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------|:-------------------| | 0 | val | Yes | T | Value to check | | 1 | i | Yes | number | Index of the value | | 2 | arr | Yes | T[] | Array of values |

| Return Type | | |-------------|------------------------------------------------| | boolean | True if the item is unique in the array so far |

groups

fn.groups;

Collection of functions that can be used with ArrayTools.group

bySize

fn.bySize(size: number): (value: T, index: number, array: T[]) => number
fn.groups.bySize(size: number): (value: T, index: number, array: T[]) => number
groups.bySize(size: number): (value: T, index: number, array: T[]) => number

Group an array into groups of a given size.

Note: The last group may be smaller than the given size.

Note: The groups a distributed in order, so the first group will be filled up first, then the next, etc.

Note: Consider using ArrayTools.partition instead

const nums = [1, 2, 3, 4, 5, 6, 7, 8];
ArrayTools.group(nums, fn.bySize(3)); // [[1, 2, 3], [4, 5, 6], [7, 8]]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------|:-------------------| | 0 | size | Yes | number | Size of the groups |

| Return Type | | |---------------------------------------------------|-------------------------------------| | (value: T, index: number, array: T[]) => number | Function to use in ArrayTools.group |

byNumGroups

fn.byNumGroups(numGroups: number): (value: T, index: number, array: T[]) => any
fn.groups.byNumGroups(numGroups: number): (value: T, index: number, array: T[]) => any
groups.byNumGroups(numGroups: number): (value: T, index: number, array: T[]) => any

Group an array into a certain number of groups as evenly as possible.

Note: The groups are distributed in order, so the first group will be filled up first, then the next, etc.

const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ArrayTools.group(nums, fn.byNumGroups(3)); // [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------|:---------------------------| | 0 | numGroups | Yes | number | Number of groups to create |

| Return Type | | |------------------------------------------------|-------------------------------------| | (value: T, index: number, array: T[]) => any | Function to use in ArrayTools.group |

ArrayTools

A collection of useful array functions.

create

create(length: number, value: T): T[]
ArrayTools.create(length: number, value: T): T[]

Create an array of the given length, where each value is the given value

ArrayTools.create(3); // [ 1, 1, 1 ]
ArrayTools.create(3, 'a'); // [ 'a', 'a', 'a' ]
ArrayTools.create(3, 1); // [ 1, 1, 1 ]

| # | Parameter Name | Required | Type | Default | Description | |:---:|:---------------|:---------|:---------|:--------------------|:------------------------------| | 0 | length | No | number | 1 | Length of the array to create | | 1 | value | No | T | 1 as unknown as T | Value to fill the array with |

| Return Type | | |-------------|----------------------------------------------------| | T[] | Array of the given length, full of the given value |

filled

filled(length: number, value: T): T[]
ArrayTools.filled(length: number, value: T): T[]

Create an array of the given length, where each value is the given value

ArrayTools.filled(3); // [ 1, 1, 1 ]
ArrayTools.filled(3, 'a'); // [ 'a', 'a', 'a' ]
ArrayTools.filled(3, 1); // [ 1, 1, 1 ]

| # | Parameter Name | Required | Type | Default | Description | |:---:|:---------------|:---------|:---------|:--------|:------------------------------| | 0 | length | No | number | 1 | Length of the array to create | | 1 | value | Yes | T | | Value to fill the array with |

| Return Type | | |-------------|----------------------------------------------------| | T[] | Array of the given length, full of the given value |

range

range(length: number, multiplier: number, offset: number): number[]
ArrayTools.range(length: number, multiplier: number, offset: number): number[]

Returns an array of the given length, where each value is equal to it's index e.g. [0, 1, 2, ..., length]

ArrayTools.range(3);  // [0, 1, 2]
ArrayTools.range(5);  // [0, 1, 2, 3, 4]
ArrayTools.range(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

ArrayTools.range(3, 2);  // [0, 2, 4]
ArrayTools.range(5, 2);  // [0, 2, 4, 6, 8]
ArrayTools.range(10, 10); // [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

| # | Parameter Name | Required | Type | Default | Description | |:---:|:---------------|:---------|:---------|:--------|:-----------------------------------------------------| | 0 | length | No | number | 1 | Length of the array to create | | 1 | multiplier | No | number | 1 | Multiplier to apply to each value | | 2 | offset | No | number | 0 | Offset to apply to each value (after the multiplier) |

| Return Type | | |-------------|--------------------------------------------------------------------| | number[] | Array of the given length, where each value is equal to it's index |

zip

zip(...arrs: T[]): ZippedArrays<T>[]
ArrayTools.zip(...arrs: T[]): ZippedArrays<T>[]

Converts multiple arrays into an array of 'tuples' for each value at the corresponding indexes.

Limited to the length of the shortest provided array

Inspired by python's 'zip'

ArrayTools.zip([1, 2, 3, 4], ['a', 'b', 'c']); // [ [1, 'a'], [2, 'b'], [3, 'c'] ]

| # | Parameter Name | Required | Type | Description | |:----:|:---------------|:---------|:------|:-----------------------| | 0… | arrs | No | T[] | Arrays to zip together |

| Return Type | | |---------------------|---------------------------------------------------------------| | ZippedArrays<T>[] | Array of 'tuples' for each value at the corresponding indexes |

zipMax

zipMax(...arrs: T[]): ZippedArrays<T>[]
ArrayTools.zipMax(...arrs: T[]): ZippedArrays<T>[]

Converts multiple arrays into an array of 'tuples' for each value at the corresponding indexes.

Unlike zip, it will match the length of the longest provided array, filling in any missing values with undefined

Inspired by python's 'zip'

ArrayTools.zipMax([1, 2, 3, 4], ['a', 'b', 'c']); //[ [ 1, 'a' ], [ 2, 'b' ], [ 3, 'c' ], [ 4, undefined ] ]

| # | Parameter Name | Required | Type | Description | |:----:|:---------------|:---------|:------|:-----------------------| | 0… | arrs | No | T[] | Arrays to zip together |

| Return Type | | |---------------------|---------------------------------------------------------------| | ZippedArrays<T>[] | Array of 'tuples' for each value at the corresponding indexes |

sortByMapped

sortByMapped(arr: T[], mapFn: (value: T, index: number, array: T[]) => M, sortFn: (a: M, b: M) => number): T[]
ArrayTools.sortByMapped(arr: T[], mapFn: (value: T, index: number, array: T[]) => M, sortFn: (a: M, b: M) => number): T[]

Sort an array by a mapped form of the values, but returning the initial values

ArrayTools.sortByMapped(['2p', '3p', '1p'], (v) => Number(v.replace('p', ''))); // ['1p', '2p', '3p']
ArrayTools.sortByMapped(
  ['2p', '3p', '1p'],
  (v) => Number(v.replace('p', '')),
  (a, b) => b - a
); // ['3p', '2p', '1p']

| # | Parameter Name | Required | Type | Default | Description | |:---:|:---------------|:---------|:---------------------------------------------|:---------|:--------------------------------------| | 0 | arr | Yes | T[] | | Array to sort | | 1 | mapFn | Yes | (value: T, index: number, array: T[]) => M | | Function to map the values to | | 2 | sortFn | No | (a: M, b: M) => number | fn.asc | Function to sort the mapped values by |

| Return Type | | |-------------|----------------------------| | T[] | Sorted array (non-mutated) |

randomise

randomise(arr: T[]): T[]
ArrayTools.randomise(arr: T[]): T[]

Returns a clone of the provided array with it's items in a random order

ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 5, 3, 4, 1, 2, 6 ]
ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 5, 1, 3, 2, 4, 6 ]
ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 6, 1, 4, 5, 2, 3 ]
ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 1, 4, 5, 2, 3, 6 ]
ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 2, 6, 1, 3, 4, 5 ]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:------|:-------------------| | 0 | arr | Yes | T[] | Array to randomise |

| Return Type | | |-------------|--------------------------------| | T[] | Randomised array (non-mutated) |

reverse

reverse(arr: T[]): T[]
ArrayTools.reverse(arr: T[]): T[]

Returns a new array with the order reversed without affecting original array

const arr1 = [1, 2, 3];
arr1            // [1, 2, 3]
arr1.reverse(); // [3, 2, 1]
arr1            // [3, 2, 1] - mutated

const arr2 = [1, 2, 3];
arr2            // [1, 2, 3]
ArrayTools.reverse(arr2);  // [3, 2, 1]
arr2            // [1, 2, 3] - not mutated

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:------|:-----------------| | 0 | arr | Yes | T[] | Array to reverse |

| Return Type | | |-------------|------------------------------| | T[] | Reversed array (non-mutated) |

entries

entries(arr: T[]): [number, T][]
ArrayTools.entries(arr: T[]): [number, T][]

Returns array of 'tuples' of index/value pairs

const arr = ['a', 'b', 'c'];
ArrayTools.entries(arr); // [ [0, 'a'], [1, 'b'], [2, 'c'] ]

for (let [index, value] of ArrayTools.entries(arr)) {
 console.log(index); // 0, 1, 2
 console.log(value); // 'a', 'b', 'c'
}

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:------|:--------------------------| | 0 | arr | Yes | T[] | Array to get entries from |

| Return Type | | |-----------------|----------------------------------------| | [number, T][] | Array of 'tuples' of index/value pairs |

repeat

repeat(maxLength: number, ...items: T[]): T[]
ArrayTools.repeat(maxLength: number, ...items: T[]): T[]

Returns an array with the given items repeated

ArrayTools.repeat(5, 'a'); // [ 'a', 'a', 'a', 'a', 'a' ]
ArrayTools.repeat(5, 'a', 'b'); // [ 'a', 'b', 'a', 'b', 'a' ]

| # | Parameter Name | Required | Type | Description | |:----:|:---------------|:---------|:---------|:----------------------------| | 0 | maxLength | Yes | number | Maximum length of the array | | 1… | items | No | T[] | Items to repeat |

| Return Type | | |-------------|-------------------------------------| | T[] | Array with the given items repeated |

roll

roll(distance: number, arr: T[]): T[]
ArrayTools.roll(distance: number, arr: T[]): T[]

'Roll' the array by a given amount so that is has a new first item. Length and contents remain the same, but the order is changed

ArrayTools.roll(1, [0, 1, 2, 3, 4, 5, 6, 7]); // [ 1, 2, 3, 4, 5, 6, 7, 0 ]
ArrayTools.roll(4, [0, 1, 2, 3, 4, 5, 6, 7]); // [ 4, 5, 6, 7, 0, 1, 2, 3 ]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------|:------------------------------| | 0 | distance | Yes | number | Distance to roll the array by | | 1 | arr | Yes | T[] | Array to roll |

| Return Type | | |-------------|----------------------------| | T[] | Rolled array (non-mutated) |

sortNumberedText

sortNumberedText(texts: string[], ignoreCase: boolean): string[]
ArrayTools.sortNumberedText(texts: string[], ignoreCase: boolean): string[]

Alphabetically sorts a list of strings, but keeps multi-digit numbers in numerical order (rather than alphabetical)

const names = ['name1', 'name10', 'name2', 'foo20', 'foo10', 'foo9'];
names.sort(); // [ 'foo10', 'foo20', 'foo9', 'name1', 'name10', 'name2' ]
ArrayTools.sortNumberedText(names); // [ 'foo9', 'foo10', 'foo20', 'name1', 'name2', 'name10' ]

| # | Parameter Name | Required | Type | Default | Description | |:---:|:---------------|:---------|:-----------|:--------|:------------------------------------| | 0 | texts | Yes | string[] | | Texts to sort | | 1 | ignoreCase | No | boolean | true | Whether to ignore case when sorting |

| Return Type | | |-------------|----------------------------| | string[] | Sorted array (non-mutated) |

partition

partition(array: T[], partitionSize: number): T[][]
ArrayTools.partition(array: T[], partitionSize: number): T[][]

Breaks an array into smaller arrays of a given size

ArrayTools.partition([1, 2, 3, 4], 3); // [ [ 1, 2, 3 ], [ 4 ] ]

ArrayTools.partition([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3); // [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ], [ 10 ] ]
ArrayTools.partition([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 4); // [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10 ] ]
ArrayTools.partition([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5); // [ [ 1, 2, 3, 4, 5 ], [ 6, 7, 8, 9, 10 ] ]

| # | Parameter Name | Required | Type | Default | Description | |:---:|:----------------|:---------|:---------|:------------------------------|:-----------------------| | 0 | array | Yes | T[] | | Array to partition | | 1 | partitionSize | No | number | Math.ceil(array.length / 2) | Size of each partition |

| Return Type | | |-------------|--------------------------------------------------------------------| | T[][] | Array of arrays, each containing a partition of the original array |

partitionEvenly

partitionEvenly(array: T[], maxPartitionSize: number): T[][]
ArrayTools.partitionEvenly(array: T[], maxPartitionSize: number): T[][]

Breaks an array into smaller arrays of a given size, but tries to keep the sizes as even as possible

ArrayTools.partitionEvenly([1, 2, 3, 4], 3); // [ [ 1, 2 ], [ 3, 4 ] ]

ArrayTools.partitionEvenly([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3); // [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8 ], [ 9, 10 ] ]
ArrayTools.partitionEvenly([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 4); // [ [ 1, 2, 3, 4 ], [ 5, 6, 7 ], [ 8, 9, 10 ] ]
ArrayTools.partitionEvenly([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5); // [ [ 1, 2, 3, 4, 5 ], [ 6, 7, 8, 9, 10 ] ]

| # | Parameter Name | Required | Type | Default | Description | |:---:|:-------------------|:---------|:---------|:------------------------------|:-------------------------------| | 0 | array | Yes | T[] | | Array to partition | | 1 | maxPartitionSize | No | number | Math.ceil(array.length / 2) | Maximum size of each partition |

| Return Type | | |-------------|--------------------------------------------------------------------| | T[][] | Array of arrays, each containing a partition of the original array |

groupObj

groupObj(array: T[], mapFn: (item: T, index: number, arr: T[]) => string | number): { [id: string]: T[]; [id: number]: T[]; }
ArrayTools.groupObj(array: T[], mapFn: (item: T, index: number, arr: T[]) => string | number): { [id: string]: T[]; [id: number]: T[]; }

Group items from an array into an object of arrays, based on a given map function.

const arr = [
  { group: 1, name: 'a' },
  { group: 2, name: 'b' },
  { group: 1, name: 'c' },
];
ArrayTools.groupObj(arr, item => item.group); // {
//   1: [ { group: 1, name: 'a' }, { group: 1, name: 'c' } ],
//   2: [ { group: 2, name: 'b' } ]
// }

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------------------------------------------------------|:------------------------------------------------| | 0 | array | Yes | T[] | Array to group | | 1 | mapFn | Yes | (item: T, index: number, arr: T[]) => string \| number | Map function to get the group key for each item |

| Return Type | | |---------------------------------------------|-------------------------------------------------------------| | { [id: string]: T[]; [id: number]: T[]; } | Object with the group keys as keys, and the items as values |

group

group(array: T[], mapFn: (item: T, index: number, arr: T[]) => string | number): T[][]
ArrayTools.group(array: T[], mapFn: (item: T, index: number, arr: T[]) => string | number): T[][]

Group items from an array into an array of arrays, based on a given map function.

const arr = [
  { group: 1, name: 'a' },
  { group: 2, name: 'b' },
  { group: 1, name: 'c' },
];
ArrayTools.group(arr, item => item.group); // [
//   [ { group: 1, name: 'a' }, { group: 1, name: 'c' } ],
//   [ { group: 2, name: 'b' } ]
// ]

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:---------------------------------------------------------|:------------------------------------------------| | 0 | array | Yes | T[] | Array to group | | 1 | mapFn | Yes | (item: T, index: number, arr: T[]) => string \| number | Map function to get the group key for each item |

| Return Type | | |-------------|----------------------------------------------------------------| | T[][] | Array of arrays, each containing a group of the original array |

findAndRemove

ArrayTools.findAndRemove(array: T[], predicate: (item: T, index: number, arr: T[]) => any, ...insertItems: T[]): T

Find the first item in an array that matches a given predicate, and remove it from the array

Note: This function mutates the provided array

const arr = [1, 2, 3, 4, 5];
ArrayTools.findAndRemove(arr, (item) => item === 3); // 3
arr; // [1, 2, 4, 5]

| # | Parameter Name | Required | Type | Description | |:----:|:---------------|:---------|:--------------------------------------------|:----------------------------------------------------------------| | 0 | array | Yes | T[] | Array to mutate | | 1 | predicate | Yes | (item: T, index: number, arr: T[]) => any | Function that returns true/truthy if the item should be removed | | 2… | insertItems | No | T[] | Items to insert in place of the removed item |

| Return Type | | |-------------|-------------------------------------------| | T | The removed item (undefined if not found) |

findLastAndRemove

ArrayTools.findLastAndRemove(array: T[], predicate: (item: T, index: number, arr: T[]) => any, ...insertItems: T[]): T

Find the last item in an array that matches a given predicate, and remove it from the array

Note: This function mutates the provided array

const arr = [1, 2, 3, 4, 5];
ArrayTools.findLastAndRemove(arr, (item) => item === 3); // 3
arr; // [1, 2, 4, 5]

| # | Parameter Name | Required | Type | Description | |:----:|:---------------|:---------|:--------------------------------------------|:----------------------------------------------------------------| | 0 | array | Yes | T[] | Array to mutate | | 1 | predicate | Yes | (item: T, index: number, arr: T[]) => any | Function that returns true/truthy if the item should be removed | | 2… | insertItems | No | T[] | Items to insert in place of the removed item |

| Return Type | | |-------------|-------------------------------------------| | T | The removed item (undefined if not found) |

filterAndRemove

ArrayTools.filterAndRemove(array: T[], predicate: (item: T, index: number, arr: T[]) => any): T[]

Find the items in an array that matches a given predicate, and r