froebel
Version:
TypeScript utility library
2,146 lines (1,357 loc) • 54.8 kB
Markdown
# Froebel - a strictly typed TypeScript utility library.
This is my (WIP) personal collection of TypeScript helper functions and utilities that
I use across different projects.
Think an opinionated version of lodash, but with first-class types.
If you have an idea for a utility that might make a good addition to this collection,
please open an issue and suggest its inclusion.
Runs in Deno, Node.js, and the Browser. Get it from [deno.land](https://deno.land/x/froebel@v0.23.2)
or [npm](https://www.npmjs.com/package/froebel).
## Installation
### Using npm
```shell
npm install froebel
```
and — assuming a module-compatible system like webpack — import as:
```ts
import { someUtility } from 'froebel';
// you can also import the utility you need directly:
import memoize from 'froebel/memoize';
```
### Using Deno
```ts
import { someUtility } from "https://deno.land/x/froebel@v0.23.2/mod.ts";
// or import just the utility you need:
import memoize from "https://deno.land/x/froebel@v0.23.2/memoize.ts"
```
---
## Available Utilities
Each category also has a file exporting only the utilities in that category, so
if you want to only import utilities from one category, you could import them as
```ts
import { throttle, debounce } from "froebel/function";
```
A few utils are exported from multiple categories but will only be listed here
once. For example `isPromise` is exported from both the `promise` and the
`predicate` category.
### Table of Contents
- __`function`__
- [ident](#ident)
- [noop](#noop)
- [partial](#partial)
- [forward](#forward)
- [unary](#unary)
- [callAll](#callall)
- [pipe](#pipe)
- [applyPipe](#applypipe)
- [bundle](#bundle)
- [bundleSync](#bundlesync)
- [nullishChain](#nullishchain)
- [asyncNullishChain](#asyncnullishchain)
- [throttle](#throttle)
- [debounce](#debounce)
- [memoize](#memoize)
- [limitInvocations](#limitinvocations)
- [once](#once)
- __`list`__
- [atWrap](#atwrap)
- [zip](#zip)
- [zipWith](#zipwith)
- [unzip](#unzip)
- [unzipWith](#unzipwith)
- [batch](#batch)
- [partition](#partition)
- [shuffle](#shuffle)
- [shuffleInPlace](#shuffleinplace)
- [take](#take)
- [range](#range)
- [numberRange](#numberrange)
- [alphaRange](#alpharange)
- __`iterable`__
- [repeat](#repeat)
- [take](#take)
- __`object`__
- [pick](#pick)
- [omit](#omit)
- [map](#map)
- __`path`__
- [select](#select)
- __`equality`__
- [oneOf](#oneof)
- [equal](#equal)
- [clone](#clone)
- [merge](#merge)
- __`promise`__
- [promisify](#promisify)
- [createQueue](#createqueue)
- [isPromise](#ispromise)
- [isNotPromise](#isnotpromise)
- __`predicate`__
- [truthy](#truthy)
- [falsy](#falsy)
- [nullish](#nullish)
- [notNullish](#notnullish)
- [isFulfilled](#isfulfilled)
- [isRejected](#isrejected)
- __`string`__
- [prefix](#prefix)
- [suffix](#suffix)
- [surround](#surround)
- [capitalize](#capitalize)
- [uncapitalize](#uncapitalize)
- [upper](#upper)
- [lower](#lower)
- [snake](#snake)
- [kebab](#kebab)
- [camel](#camel)
- [pascal](#pascal)
- [screamingSnake](#screamingsnake)
- [transformCase](#transformcase)
- __`math`__
- [clamp](#clamp)
- __`data structures`__
- [BiMap](#bimap)
- [SortedArray](#sortedarray)
- [SortedMap](#sortedmap)
## Function
#### `ident`
```hs
(value: T) => T
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/ident.ts#L2)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/ident.test.ts)_</sup></sup>
> Identity function.
#### Import
```ts
/* Node: */ import ident from "froebel/ident";
/* Deno: */ import ident from "https://deno.land/x/froebel@v0.23.2/ident.ts";
```
---
#### `noop`
```hs
() => void
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/noop.ts#L1)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/noop.test.ts)_</sup></sup>
#### Import
```ts
/* Node: */ import noop from "froebel/noop";
/* Deno: */ import noop from "https://deno.land/x/froebel@v0.23.2/noop.ts";
```
---
#### `partial`
```hs
(fun: T, ...argsLeft: PL) => (...argsRight: PR) => ReturnType<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/partial.ts#L17)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/partial.test.ts)_</sup></sup>
> Partially apply a function.
#### Import
```ts
/* Node: */ import partial from "froebel/partial";
/* Deno: */ import partial from "https://deno.land/x/froebel@v0.23.2/partial.ts";
```
#### Example
```ts
const divide = (dividend: number, divisor: number) => dividend / divisor
// (divisor: number) => number
const oneOver = partial(divide, 1)
// prints: 0.25
console.log(oneOver(4))
```
---
#### `forward`
```hs
(fun: T, ...argsRight: PR) => (...argsLeft: PL) => ReturnType<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/forward.ts#L28)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/forward.test.ts)_</sup></sup>
> Given a function and its nth..last arguments, return a function accepting
> arguments 0..n-1.
#### Import
```ts
/* Node: */ import forward from "froebel/forward";
/* Deno: */ import forward from "https://deno.land/x/froebel@v0.23.2/forward.ts";
```
#### Examples
```ts
const divide = (dividend: number, divisor: number) => dividend / divisor
// (dividend: number) => number
const divideBy2 = forward(divide, 2)
// prints: 0.5
console.log(divideBy2(1))
```
```ts
const fetchUrl = async (protocol: string, domain: string, path: string) =>
await fetch(`${protocol}://${domain}/${path}`)
const fetchRepo = forward(fetchUrl, 'github.com', 'MathisBullinger/froebel')
const viaHTTPS = await fetchRepo('https')
```
---
#### `unary`
```hs
(fun: T) => Unary<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/unary.ts#L15)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/unary.test.ts)_</sup></sup>
> Turns `fun` into a unary function (a function that only accepts one
> argument).
>
> Note: `fun` must accept at least one argument and must not require more than
> one argument.
>
#### Import
```ts
/* Node: */ import unary from "froebel/unary";
/* Deno: */ import unary from "https://deno.land/x/froebel@v0.23.2/unary.ts";
```
#### Example
```ts
['1', '2', '3'].map(unary(parseInt)) // -> [1, 2, 3]
```
---
#### `callAll`
```hs
(funs: F[], ...args: P) => ReturnTypes<F>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/callAll.ts#L16)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/callAll.test.ts)_</sup></sup>
> Take a list of functions that accept the same parameters and call them all
> with the provided arguments.
#### Import
```ts
/* Node: */ import callAll from "froebel/callAll";
/* Deno: */ import callAll from "https://deno.land/x/froebel@v0.23.2/callAll.ts";
```
#### Example
```ts
const mult = (a: number, b: number) => a * b
const div = (a: number, b: number) => a / b
// prints: [8, 2]
console.log( callAll([mult, div], 4, 2) )
```
---
#### `pipe`
```hs
(...funs: T) => PipedFun<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/pipe.ts#L27)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/pipe.test.ts)_</sup></sup>
> Given a list of functions returns a function that will execute the given
> functions one after another, always passing the result of the previous
> function as an argument to the next function.
>
> If one of the given functions returns a promise, the promise will be resolved
> before being passed to the next function.
>
#### Import
```ts
/* Node: */ import pipe from "froebel/pipe";
/* Deno: */ import pipe from "https://deno.land/x/froebel@v0.23.2/pipe.ts";
```
#### Example
```ts
const join = (...chars: string[]) => chars.join('')
pipe(join, parseInt)('1', '2', '3') // -> 123
const square = (n: number) => n ** 2
// this is equivalent to: square(square(square(2)))
pipe(square, square, square)(2) // -> 256
// also works with promises:
fetchNumber :: async () => Promise<number>
pipe(fetchNumber, n => n.toString()) // async () => Promise<string>
```
---
#### `applyPipe`
```hs
(arg: Parameters<T[0]>[0], ...funs: T) => CheckPipe<T, CarryReturn<ReturnTypes<T>, Parameters<T[0]>>, false>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/pipe.ts#L57)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/pipe.test.ts)_</sup></sup>
> Like `pipe` but takes an argument as its first parameter and invokes the pipe
> with it.
>
> Note: unlike in `pipe`, the first function of the pipe must take exactly one
> argument.
>
>
> <sub>see [pipe](#pipe)</sub>
#### Import
```ts
/* Node: */ import { applyPipe } from "froebel/pipe";
/* Deno: */ import { applyPipe } from "https://deno.land/x/froebel@v0.23.2/pipe.ts";
```
#### Example
```ts
applyPipe(2, double, square, half) // -> 8
```
---
#### `bundle`
```hs
(...funs: λ<T>[]) => (...args: T) => Promise<void>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/bundle.ts#L12)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/bundle.test.ts)_</sup></sup>
> Given a list of functions that accept the same parameters, returns a function
> that takes these parameters and invokes all of the given functions.
>
> The returned function returns a promise that resolves once all functions
> returned/resolved and rejects if any of the functions throws/rejects - but
> only after all returned promises have been settled.
>
#### Import
```ts
/* Node: */ import bundle from "froebel/bundle";
/* Deno: */ import bundle from "https://deno.land/x/froebel@v0.23.2/bundle.ts";
```
---
#### `bundleSync`
```hs
(...funs: λ<T>[]) => (...args: T) => void
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/bundle.ts#L29)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/bundle.test.ts)_</sup></sup>
> Same as [bundle](#bundle), but return synchronously.
>
> If any of the functions throws an error synchronously, none of the functions
> after it will be invoked and the error will propagate.
>
#### Import
```ts
/* Node: */ import { bundleSync } from "froebel/bundle";
/* Deno: */ import { bundleSync } from "https://deno.land/x/froebel@v0.23.2/bundle.ts";
```
---
#### `nullishChain`
```hs
(...funs: [] | [FF, ...FR[]]) => (...args: Parameters<FF>) => ReturnType<FF> | ReturnType<FR[number]>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/nullishChain.ts#L26)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/nullishChain.test.ts)_</sup></sup>
> Given a list of functions that accept the same parameters, returns a function
> that given these arguments returns the result of the first function whose
> result is not nullish.
>
> This is equivalent to chaining together invocations of the passed in
> functions with the given arguments with nullish coalescing _(`??`)_ operators.
>
#### Import
```ts
/* Node: */ import { nullishChain } from "froebel/nullishChain";
/* Deno: */ import { nullishChain } from "https://deno.land/x/froebel@v0.23.2/nullishChain.ts";
```
#### Example
```ts
const isAdult = (age: number) => { if (n >= 18) return 'adult' }
const isToddler = (age: number) => { if (n <= 3) return 'toddler' }
const ageGroup = nullishChain(isAdult, isToddler, () => 'child')
// this is functionally equivalent to:
const ageGroup = age => isAdult(age) ?? isToddler(age) ?? 'child'
ageGroup(1) // prints: 'toddler'
ageGroup(10) // prints: 'child'
ageGroup(50) // prints: 'adult'
```
---
#### `asyncNullishChain`
```hs
(...funs: [] | [FF, ...FR[]]) => (...args: Parameters<FF>) => Promise<PromType<ReturnType<FF>> | PromType<ReturnType<FR[number]>>>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/nullishChain.ts#L45)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/nullishChain.test.ts)_</sup></sup>
> Same as [nullishChain](#nullishchain) but accept asynchronous functions too.
#### Import
```ts
/* Node: */ import { asyncNullishChain } from "froebel/nullishChain";
/* Deno: */ import { asyncNullishChain } from "https://deno.land/x/froebel@v0.23.2/nullishChain.ts";
```
#### Example
```ts
const readFromCache = (id: string): Resource => { if (id in cache) return cache[id] }
const readFromFile = (id: string): Resource => { if (fileExists(id)) return readFile(id) }
const fetchFromNet = async (id: string): Promise<Resource> => await fetch(`someURL/${id}`)
// async (id: string) => Promise<Resource>
const getResource = asyncNullishChain(readFromCache, readFromFile, fetchFromNet)
```
---
#### `throttle`
```hs
(fun: T, ms: number, opts?: {leading: boolean, trailing: boolean}) => λ<Parameters<T>, void> & {[cancel]: () => void}
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/throttle.ts#L14)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/throttle.test.ts)_</sup></sup>
> Create a throttled function that invokes `fun` at most every `ms` milliseconds.
>
> `fun` is invoked with the last arguments passed to the throttled function.
>
> Calling `[throttle.cancel]()` on the throttled function will cancel the currently
> scheduled invocation.
>
#### Import
```ts
/* Node: */ import throttle from "froebel/throttle";
/* Deno: */ import throttle from "https://deno.land/x/froebel@v0.23.2/throttle.ts";
```
---
#### `debounce`
```hs
(fun: T, ms: number) => λ<Parameters<T>, void> & {[cancel]: () => void}
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/debounce.ts#L14)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/debounce.test.ts)_</sup></sup>
> Creates a debounced function that delays invoking `fun` until `ms` milliseconds
> have passed since the last invocation of the debounced function.
>
> `fun` is invoked with the last arguments passed to the debounced function.
>
> Calling `[debounce.cancel]()` on the debounced function will cancel the currently
> scheduled invocation.
>
#### Import
```ts
/* Node: */ import debounce from "froebel/debounce";
/* Deno: */ import debounce from "https://deno.land/x/froebel@v0.23.2/debounce.ts";
```
---
#### `memoize`
```hs
(fun: T, opt: {limit: number, weak: W, key: (...args: Parameters<T>) => K}) => T & {cache: W extends false ? Map<K, ReturnType<T>> : Cache<K, ReturnType<T>>}
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/memoize.ts#L70)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/memoize.test.ts)_</sup></sup>
> Returns a copy of `fun` that remembers its result for any given arguments and
> only invokes `fun` for unknown arguments.
>
> The cache key is computed using the `key` function. The default `key`
> function simply stringifies the arguments.
>
> If `limit` is specified, only the `limit`-last entries are kept in cache.
>
> The function's cache is available at `memoized.cache`.
>
> If `opt.weak` is `true`, non-primitive cache keys are stored in a WeakMap.
> This behavior might for example be useful if you want to memoize some
> calculation including a DOM Node without holding on to a reference of that
> node.
> Using weak keys prohibits setting a `limit`.
>
#### Import
```ts
/* Node: */ import memoize from "froebel/memoize";
/* Deno: */ import memoize from "https://deno.land/x/froebel@v0.23.2/memoize.ts";
```
#### Examples
```ts
const expensiveCalculation = (a: number, b: number) => {
console.log(`calculate ${a} + ${b}`)
return a + b
}
const calc = memoize(expensiveCalculation)
console.log( calc(1, 2) )
// calculate 1 + 2
// 3
console.log( calc(20, 5) )
// calculate 20 + 5
// 25
console.log( calc(20, 5) )
// 25
console.log( calc(1, 2) )
// 3
calc.cache.clear()
console.log( calc(1, 2) )
// calculate 1 + 2
// 3
```
```ts
const logIfDifferent = memoize(
(msg: string) => console.log(msg),
{
limit: 1,
key: msg => msg
}
)
logIfDifferent('a')
logIfDifferent('a')
logIfDifferent('b')
logIfDifferent('a')
// a
// b
// a
```
---
#### `limitInvocations`
```hs
(fun: T, limit: number, ...funs: ExcS<T>) => T
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/invoke.ts#L19)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/invoke.test.ts)_</sup></sup>
> Returns a version of the function `fun` that can only be invoked `limit`
> times.
> An optional `except` function will be called with the same parameters on any
> additional invocations.
>
> If `fun` returns anything but `void` (or `Promise<void>`), supplying an
> `except` function is mandatory.
>
> The `except` function must have the same return type as `fun`, or — if `fun`
> returns a promise — it may return the type that the promise resolves to
> synchronously.
>
> The `except` function may also throw instead of returning a value.
>
#### Import
```ts
/* Node: */ import { limitInvocations } from "froebel/invoke";
/* Deno: */ import { limitInvocations } from "https://deno.land/x/froebel@v0.23.2/invoke.ts";
```
---
#### `once`
```hs
(fun: T, ...funs: ExcS<T>) => T
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/invoke.ts#L40)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/invoke.test.ts)_</sup></sup>
> Special case of [limitInvocations](#limitinvocations). `fun` can only be invoked once.
>
> <sub>see [limitInvocations](#limitinvocations)</sub>
#### Import
```ts
/* Node: */ import { once } from "froebel/invoke";
/* Deno: */ import { once } from "https://deno.land/x/froebel@v0.23.2/invoke.ts";
```
## List
#### `atWrap`
```hs
(arr: T[], i: number) => T
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/atWrap.ts#L3)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/atWrap.test.ts)_</sup></sup>
> Access list at `i % length`. Negative indexes start indexing the last
> element as `[-1]` and wrap around to the back.
#### Import
```ts
/* Node: */ import atWrap from "froebel/atWrap";
/* Deno: */ import atWrap from "https://deno.land/x/froebel@v0.23.2/atWrap.ts";
```
---
#### `zip`
```hs
(...lists: T) => Zip<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/zip.ts#L16)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/zip.test.ts)_</sup></sup>
> Takes multiple lists and returns a list of tuples containing the value in
> each list at the current index. If the lists are of different lengths, the
> returned list of tuples has the length of the shortest passed in list.
#### Import
```ts
/* Node: */ import zip from "froebel/zip";
/* Deno: */ import zip from "https://deno.land/x/froebel@v0.23.2/zip.ts";
```
#### Example
```ts
const pairs = zip([1,2,3], ['a','b','c'])
console.log(pairs) // prints: [[1,'a'], [2,'b'], [3,'c']]
```
---
#### `zipWith`
```hs
(zipper: (...args: {[I in string | number | symbol]: U}) => U, ...lists: T) => U[]
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/zip.ts#L35)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/zip.test.ts)_</sup></sup>
> Same as [zip](#zip) but also takes a `zipper` function, that is called for
> each index with the element at current index in each list as arguments. The
> result of `zipper` is the element at current index in the list returned from
> `zipWith`.
#### Import
```ts
/* Node: */ import { zipWith } from "froebel/zip";
/* Deno: */ import { zipWith } from "https://deno.land/x/froebel@v0.23.2/zip.ts";
```
#### Example
```ts
const sums = zipWith((a,b) => a+b, [1,2,3], [4,5,6])
console.log(sums) // prints: [5,7,9]
```
---
#### `unzip`
```hs
(...zipped: T[][]) => Unzip<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/unzip.ts#L15)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/unzip.test.ts)_</sup></sup>
> Reverse of [zip](#zip). Takes a list of tuples and deconstructs them into
> an array (of length of the tuples length) of lists each containing all the
> elements in all tuples at the lists index.
#### Import
```ts
/* Node: */ import unzip from "froebel/unzip";
/* Deno: */ import unzip from "https://deno.land/x/froebel@v0.23.2/unzip.ts";
```
#### Example
```ts
const [nums, chars] = unzip([1,'a'], [2,'b'], [3,'c'])
console.log(nums) // prints: [1, 2, 3]
console.log(chars) // prints: ['a','b','c']
```
---
#### `unzipWith`
```hs
(zipped: T[][], ...unzippers: U) => {[I in string | number | symbol]: ReturnType<U[I]>}
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/unzip.ts#L39)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/unzip.test.ts)_</sup></sup>
> Same as [unzip](#unzip) but accepts an `unzipper` function for each tuple
> index. The `unzipper`'s return value is used as the value in the list at
> that index returned from `unzipWith`.
>
> The `unzipper` takes the current element as its first argument, an
> accumulator as second argument (initially `undefined`) and its return value
> is the accumulator passed into the next invocation.
>
#### Import
```ts
/* Node: */ import { unzipWith } from "froebel/unzip";
/* Deno: */ import { unzipWith } from "https://deno.land/x/froebel@v0.23.2/unzip.ts";
```
#### Example
```ts
const [nums, str] = unzipWith(
[ [1,'a'], [2,'b'], [3,'c'] ],
(n, acc: number[] = []) => [...acc, n],
(c, str = '') => str + c
)
console.log(nums) // prints: [1, 2, 3]
console.log(str) // prints: 'abc'
```
---
#### `batch`
```hs
(list: T[], batchSize: number) => T[][]
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/batch.ts#L14)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/batch.test.ts)_</sup></sup>
> Takes a `list` and returns it in multiple smaller lists of the size
> `batchSize`.
> The last batch may be smaller than `batchSize` depending on if `list` size is
> divisible by `batchSize`.
#### Import
```ts
/* Node: */ import batch from "froebel/batch";
/* Deno: */ import batch from "https://deno.land/x/froebel@v0.23.2/batch.ts";
```
#### Example
```ts
batch([1,2,3,4,5], 2) // -> [ [1,2], [3,4], [5] ]
```
---
#### `partition`
```hs
(list: T[], predicate: (el: T) => el is S) => [S[], Exclude<T, S>[]]
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/partition.ts#L30)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/partition.test.ts)_</sup></sup>
> Takes a `list` and returns a pair of lists containing: the elements that
> match the `predicate` and those that don't, respectively.
>
> Think of it as `filter`, but the elements that don't pass the filter aren't
> discarded but returned in a separate list instead.
>
#### Import
```ts
/* Node: */ import partition from "froebel/partition";
/* Deno: */ import partition from "https://deno.land/x/froebel@v0.23.2/partition.ts";
```
#### Example
```ts
const [strings, numbers] = partition(
['a', 'b', 1, 'c', 2, 3],
(el): el is string => typeof el === 'string'
)
// strings: ["a", "b", "c"]
// numbers: [1, 2, 3]
```
---
#### `shuffle`
```hs
(list: T[]) => T[]
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/shuffle.ts#L5)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/shuffle.test.ts)_</sup></sup>
> Shuffles `list` using the Fisher-Yates shuffle algorithm.
> The original `list` is not modified and the shuffled list is returned.
#### Import
```ts
/* Node: */ import shuffle from "froebel/shuffle";
/* Deno: */ import shuffle from "https://deno.land/x/froebel@v0.23.2/shuffle.ts";
```
---
#### `shuffleInPlace`
```hs
(list: unknown[]) => void
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/shuffle.ts#L16)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/shuffle.test.ts)_</sup></sup>
> Same as [shuffle](#shuffle) but shuffles `list` in place.
#### Import
```ts
/* Node: */ import { shuffleInPlace } from "froebel/shuffle";
/* Deno: */ import { shuffleInPlace } from "https://deno.land/x/froebel@v0.23.2/shuffle.ts";
```
---
#### `take`
```hs
(n: number, list: Iterable<T>) => T[]
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/take.ts#L11)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/take.test.ts)_</sup></sup>
> Takes `n` elements from the iterable `list` and returns them as an array.
#### Import
```ts
/* Node: */ import { take } from "froebel/list";
/* Deno: */ import { take } from "https://deno.land/x/froebel@v0.23.2/list.ts";
```
#### Example
```ts
take(5, repeat(1, 2)) // -> [1, 2, 1, 2, 1]
take(3, [1, 2, 3, 4]) // -> [1, 2, 3]
take(3, [1, 2]) // -> [1, 2]
```
---
#### `range`
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/range.ts#L66)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/range.test.ts)_</sup></sup>
> Creates a range between two values.
>
> <sub>see [numberRange](#numberrange) and [alphaRange](#alpharange)</sub>
#### Import
```ts
/* Node: */ import range from "froebel/range";
/* Deno: */ import range from "https://deno.land/x/froebel@v0.23.2/range.ts";
```
---
#### `numberRange`
```hs
(start: number, end: number, step: number) => number[]
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/range.ts#L17)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/range.test.ts)_</sup></sup>
> Constructs a numeric between `start` and `end` inclusively.
#### Import
```ts
/* Node: */ import { numberRange } from "froebel/range";
/* Deno: */ import { numberRange } from "https://deno.land/x/froebel@v0.23.2/range.ts";
```
#### Example
```ts
range(2, 6) // -> [2, 3, 4, 5, 6]
range(8, 9, .3) // -> [8, 8.3, 8.6, 8.9]
range(3, -2) // -> [3, 2, 1, 0, -1, -2]
```
---
#### `alphaRange`
```hs
(start: string, end: string) => string[]
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/range.ts#L43)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/range.test.ts)_</sup></sup>
> Constructs a range between characters.
#### Import
```ts
/* Node: */ import { alphaRange } from "froebel/range";
/* Deno: */ import { alphaRange } from "https://deno.land/x/froebel@v0.23.2/range.ts";
```
#### Example
```ts
range('a', 'd') // -> ['a', 'b', 'c', 'd']
range('Z', 'W') // -> ['Z', 'Y', 'X', 'W']
```
## Iterable
#### `repeat`
```hs
(...sequence: [T, ...T[]]) => Generator<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/repeat.ts#L11)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/repeat.test.ts)_</sup></sup>
> Returns a generator that repeats `sequence`.
#### Import
```ts
/* Node: */ import repeat from "froebel/repeat";
/* Deno: */ import repeat from "https://deno.land/x/froebel@v0.23.2/repeat.ts";
```
#### Example
```ts
// prints: 1, 2, 3, 1, 2, 3, ...
for (const n of repeat(1, 2, 3))
console.log(n)
```
---
#### `take`
```hs
(n: number, list: Iterable<T>) => Generator<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/take.ts#L25)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/take.test.ts)_</sup></sup>
> Takes `n` elements from the iterable `list` and returns them as a generator.
#### Import
```ts
/* Node: */ import { take } from "froebel/iterable";
/* Deno: */ import { take } from "https://deno.land/x/froebel@v0.23.2/iterable.ts";
```
#### Example
```ts
[...take(5, repeat(1, 2))] // -> [1, 2, 1, 2, 1]
[...take(3, [1, 2, 3, 4])] // -> [1, 2, 3]
[...take(3, [1, 2])] // -> [1, 2]
```
## Object
#### `pick`
```hs
(obj: T, ...keys: K[]) => Pick<T, K>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/pick.ts#L9)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/pick.test.ts)_</sup></sup>
> From `obj`, create a new object that only includes `keys`.
#### Import
```ts
/* Node: */ import pick from "froebel/pick";
/* Deno: */ import pick from "https://deno.land/x/froebel@v0.23.2/pick.ts";
```
#### Example
```ts
pick({ a: 1, b: 2, c: 3 }, 'a', 'c') // { a: 1, c: 3 }
```
---
#### `omit`
```hs
(obj: T, ...keys: K[]) => Omit<T, K>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/omit.ts#L9)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/omit.test.ts)_</sup></sup>
> From `obj`, create a new object that does not include `keys`.
#### Import
```ts
/* Node: */ import omit from "froebel/omit";
/* Deno: */ import omit from "https://deno.land/x/froebel@v0.23.2/omit.ts";
```
#### Example
```ts
omit({ a: 1, b: 2, c: 3 }, 'a', 'c') // { b: 2 }
```
---
#### `map`
```hs
(data: Map<IK, IV>, callback: (key: IK, value: IV) => [OK, OV]) => Map<OK, OV>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/map.ts#L34)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/map.test.ts)_</sup></sup>
> Map over `data`. `data` can be a regular object, a `Map`, a `Set`, or an
> array.
#### Import
```ts
/* Node: */ import map from "froebel/map";
/* Deno: */ import map from "https://deno.land/x/froebel@v0.23.2/map.ts";
```
#### Examples
```ts
// -> { a: 1, b: 2 }
map({ a: '1', b: '2' }, (key, value) => [key, parseInt(value)])
```
```ts
// -> Map([ [2, 1], [4, 3] ])
map(new Map([ [1, 2], [3, 4] ]), (key, value) => [key + 1, value - 1])
```
## Path
#### `select`
```hs
(obj: T, ...path: P) => PickPath<T, P>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/select.ts#L16)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/select.test.ts)_</sup></sup>
> Returns the value in `obj` at `path`. If the given path does not exist,
> the symbol `none` is returned.
#### Import
```ts
/* Node: */ import select from "froebel/select";
/* Deno: */ import select from "https://deno.land/x/froebel@v0.23.2/select.ts";
```
#### Example
```ts
// -> 'something'
select(
{ a: { deeply: [{ nested: { object: 'something' } }] } },
'a', 'deeply', 0, 'nested', 'object'
)
```
## Equality
#### `oneOf`
```hs
(value: T, ...cmps: TT) => value is TT[number]
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/oneOf.ts#L2)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/oneOf.test.ts)_</sup></sup>
> Checks if `v` is one of `cmps`.
#### Import
```ts
/* Node: */ import oneOf from "froebel/oneOf";
/* Deno: */ import oneOf from "https://deno.land/x/froebel@v0.23.2/oneOf.ts";
```
---
#### `equal`
```hs
(a: unknown, b: unknown) => boolean
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/equal.ts#L9)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/equal.test.ts)_</sup></sup>
> Checks if `a` and `b` are structurally equal using the following algorithm:
>
> - primitives are compared by value
> - functions are compared by reference
> - objects (including arrays) are checked to have the same properties and
> their values are compared recursively using the same algorithm
>
#### Import
```ts
/* Node: */ import equal from "froebel/equal";
/* Deno: */ import equal from "https://deno.land/x/froebel@v0.23.2/equal.ts";
```
---
#### `clone`
```hs
(value: T) => T
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/clone.ts#L15)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/clone.test.ts)_</sup></sup>
> Returns a copied version of `value`.
>
> If `value` is primitive, returns `value`.
> Otherwise, properties of `value` are copied recursively. Only `value`'s own
> enumerable properties are cloned. Arrays are cloned by mapping over their
> elements.
>
> If a path in `value` references itself or a parent path, then in the
> resulting object that path will also reference the path it referenced in the
> original object (but now in the resuling object instead of the original).
>
#### Import
```ts
/* Node: */ import clone from "froebel/clone";
/* Deno: */ import clone from "https://deno.land/x/froebel@v0.23.2/clone.ts";
```
---
#### `merge`
```hs
(a: A, b: B) => Merge<A, B>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/merge.ts#L76)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/merge.test.ts)_</sup></sup>
> Recursively merges `A` and `B`. If a property in `A` and `B` is of a
> different type (i.e. it's not an array, Set, Map, or plain object in both,
> the value from `B` will be used in the result).
>
> If there are self-references in the cloned values, array / Set items, or Map
> keys or values, they will also be self-referencing in the result.
>
#### Import
```ts
/* Node: */ import merge from "froebel/merge";
/* Deno: */ import merge from "https://deno.land/x/froebel@v0.23.2/merge.ts";
```
## Promise
#### `promisify`
```hs
(withCallback: T, resultIndex?: N, errorIndex: null | number) => Promisified<T, N>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/promisify.ts#L56)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/promisify.test.ts)_</sup></sup>
> Turns a function accepting a callback into a function returning a promise.
> You can specify in which parameter (if any) the callback expects to receive
> a result and in which it expects an error.
> Pass `null` to `resultIndex` or `errorIndex` if no result or errors are
> passed to the callback. By default the first argument passed to the callback
> is interpreted as result and none of the arguments as error (if the function
> accepting the callback throws or rejects, that will still result in the
> promisified function rejecting).
>
> The `callbackFirst` property allows passing additional parameters after the
> callback and `callbackLast` will pass additional parameters before the
> callback.
>
#### Import
```ts
/* Node: */ import promisify from "froebel/promisify";
/* Deno: */ import promisify from "https://deno.land/x/froebel@v0.23.2/promisify.ts";
```
#### Examples
```ts
const notify = (cb: (msg: string) => void) => { msg('something') }
const waitForMessage = promisify(notify)
await waitForMessage() // -> 'something'
// here result is passed at index 1 and errors at index 0.
const callbackAPI = (cb: (error?: Error, data?: unknown) => void) => {}
const asyncAPI = promisify(callbackAPI, 1, 0)
```
```ts
const sleep = promisify(setTimeout).callbackFirst
await sleep(200)
```
```ts
const fs = require('node:fs');
const stat = promisify(fs.stat, 1, 0).callbackLast
try {
const stats = await stat('.');
console.log(`This directory is owned by ${stats.uid}`);
} catch (err) {
console.error(err)
}
```
---
#### `createQueue`
```hs
() => Queue
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/queue.ts#L46)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/queue.test.ts)_</sup></sup>
> Creates a `queue` function that accepts a function as it's only parameter.
> When `queue` is invoked, the passed in function is executed after the last
> function passed to `queue` has finished executing. The `queue` function
> returns the result of the passed in function asynchronously.
>
> Reading `queue.done` is `true` if no functions are currently executing /
> scheduled and otherwise a promise that resolves once the last function has
> stopped executing and no futher functions are queued.
>
#### Import
```ts
/* Node: */ import createQueue from "froebel/queue";
/* Deno: */ import createQueue from "https://deno.land/x/froebel@v0.23.2/queue.ts";
```
#### Example
```ts
const queue = createQueue()
queue(async () => {
console.log('start a')
await delay()
return 'end a'
}).then(console.log)
queue(async () => {
console.log('start b')
await delay()
return 'end b'
}).then(console.log)
queue(async () => {
console.log('start c')
await delay()
return 'end c'
}).then(console.log)
await queue.done
// start a
// end a
// start b
// end b
// start c
// end c
```
---
#### `isPromise`
```hs
(value: unknown) => value is Promise<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/isPromise.ts#L2)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/isPromise.test.ts)_</sup></sup>
> Checks if `value` looks like a promise.
#### Import
```ts
/* Node: */ import isPromise from "froebel/isPromise";
/* Deno: */ import isPromise from "https://deno.land/x/froebel@v0.23.2/isPromise.ts";
```
---
#### `isNotPromise`
```hs
(value: T) => value is Exclude<T, Promise<any>>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/isPromise.ts#L19)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/isPromise.test.ts)_</sup></sup>
> Checks if `value` is not a promise.
#### Import
```ts
/* Node: */ import { isNotPromise } from "froebel/isPromise";
/* Deno: */ import { isNotPromise } from "https://deno.land/x/froebel@v0.23.2/isPromise.ts";
```
#### Example
```ts
(value: number | Promise<unknown>) => {
if (isNotPromise(value)) return value / 2
}
```
## Predicate
#### `truthy`
```hs
(value: T) => value is PickTruthy<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/truthy.ts#L2)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/truthy.test.ts)_</sup></sup>
> Checks if `value` is truthy. Literal types are narrowed accordingly.
#### Import
```ts
/* Node: */ import { truthy } from "froebel/truthy";
/* Deno: */ import { truthy } from "https://deno.land/x/froebel@v0.23.2/truthy.ts";
```
---
#### `falsy`
```hs
(value: T) => value is PickFalsy<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/truthy.ts#L5)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/truthy.test.ts)_</sup></sup>
> Checks if `value` is falsy. Literal types are narrowed accordingly.
#### Import
```ts
/* Node: */ import { falsy } from "froebel/truthy";
/* Deno: */ import { falsy } from "https://deno.land/x/froebel@v0.23.2/truthy.ts";
```
---
#### `nullish`
```hs
(value: T) => value is Nullish<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/nullish.ts#L2)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/nullish.test.ts)_</sup></sup>
> Checks if `value` is nullish. Literal types are narrowed accordingly.
#### Import
```ts
/* Node: */ import { nullish } from "froebel/nullish";
/* Deno: */ import { nullish } from "https://deno.land/x/froebel@v0.23.2/nullish.ts";
```
---
#### `notNullish`
```hs
(value: null | T) => value is T
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/nullish.ts#L20)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/nullish.test.ts)_</sup></sup>
> Checks if `value` is not nullish. Literal types are narrowed accordingly.
#### Import
```ts
/* Node: */ import { notNullish } from "froebel/nullish";
/* Deno: */ import { notNullish } from "https://deno.land/x/froebel@v0.23.2/nullish.ts";
```
#### Example
```ts
const nums = (...values: (number | undefined)[]): number[] => values.filter(notNullish)
```
---
#### `isFulfilled`
```hs
(result: PromiseSettledResult<T>) => result is PromiseFulfilledResult<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/settled.ts#L2)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/settled.test.ts)_</sup></sup>
> Checks if `result` (returned from `Promise.allSettled`) is fulfilled.
#### Import
```ts
/* Node: */ import { isFulfilled } from "froebel/settled";
/* Deno: */ import { isFulfilled } from "https://deno.land/x/froebel@v0.23.2/settled.ts";
```
---
#### `isRejected`
```hs
(result: PromiseSettledResult<unknown>) => result is PromiseRejectedResult
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/settled.ts#L7)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/settled.test.ts)_</sup></sup>
> Checks if `result` (returned from `Promise.allSettled`) is rejected.
#### Import
```ts
/* Node: */ import { isRejected } from "froebel/settled";
/* Deno: */ import { isRejected } from "https://deno.land/x/froebel@v0.23.2/settled.ts";
```
## String
#### `prefix`
```hs
(prefix: T0, str: T1, caseMod?: C) => `${string}`
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/prefix.ts#L12)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/prefix.test.ts)_</sup></sup>
> Returns `str` prefixed with `prefix`. Optionally, allows prefxing in camel
> case, i.e. `prefix('foo', 'bar', 'camel') => 'fooBar'`, or snake case, i.e.
> `prefix('foo', 'bar', 'snake') => 'foo_bar'`.
>
> The result is strictly typed, so `prefix('foo', 'bar')` will return the type
> `'foobar'`, not just a generic `string`.
>
#### Import
```ts
/* Node: */ import prefix from "froebel/prefix";
/* Deno: */ import prefix from "https://deno.land/x/froebel@v0.23.2/prefix.ts";
```
---
#### `suffix`
```hs
(str: T1, suffix: T0, caseMod?: C) => `${string}`
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/suffix.ts#L8)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/suffix.test.ts)_</sup></sup>
> Returns `str` suffixed with `suffix`. Same case and type behavior as
> [prefix](#prefix).
#### Import
```ts
/* Node: */ import suffix from "froebel/suffix";
/* Deno: */ import suffix from "https://deno.land/x/froebel@v0.23.2/suffix.ts";
```
---
#### `surround`
```hs
(str: A, surrounding: B) => B extends "" ? A : Surround<A, B>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/surround.ts#L13)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/surround.test.ts)_</sup></sup>
> Surrounds the `str` with `surrounding`. `surrounding` must have an even length.
#### Import
```ts
/* Node: */ import { surround } from "froebel/surround";
/* Deno: */ import { surround } from "https://deno.land/x/froebel@v0.23.2/surround.ts";
```
#### Example
```ts
surround("foo", "()") // "(foo)"
surround("foo", "({[]})") // "({[foo]})"
```
---
#### `capitalize`
```hs
(str: T) => Capitalize
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L12)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Upper-case first letter of string.
#### Import
```ts
/* Node: */ import { capitalize } from "froebel/case";
/* Deno: */ import { capitalize } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
---
#### `uncapitalize`
```hs
(str: T) => Uncapitalize
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L16)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Lower-case first letter of string
#### Import
```ts
/* Node: */ import { uncapitalize } from "froebel/case";
/* Deno: */ import { uncapitalize } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
---
#### `upper`
```hs
(str: T) => Uppercase
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L20)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Strictly typed `String.toUpperCase()`.
#### Import
```ts
/* Node: */ import { upper } from "froebel/case";
/* Deno: */ import { upper } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
---
#### `lower`
```hs
(str: T) => Lowercase
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L24)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Strictly typed `String.toLowerCase()`.
#### Import
```ts
/* Node: */ import { lower } from "froebel/case";
/* Deno: */ import { lower } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
---
#### `snake`
```hs
(str: T) => DelimitedCase<T, "_">
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L40)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Transforms a variable name to snake case.
>
> Note: The rules for transforming anything to snake case are somewhat vague.
> So use this only for very simple names where the resulting value is
> absolutely unambiguous. For more examples of how names are transformed, have
> a look at the test cases.
>
#### Import
```ts
/* Node: */ import { snake } from "froebel/case";
/* Deno: */ import { snake } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
#### Example
```ts
snake('fooBar') // 'foo_bar'
```
---
#### `kebab`
```hs
(str: T) => DelimitedCase<T, "-">
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L64)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Transforms a variable name to kebab case.
>
> Note: The rules for transforming anything to kebab case are somewhat vague.
> So use this only for very simple names where the resulting value is
> absolutely unambiguous. For more examples of how names are transformed, have
> a look at the test cases.
>
#### Import
```ts
/* Node: */ import { kebab } from "froebel/case";
/* Deno: */ import { kebab } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
#### Example
```ts
kebab('fooBar') // 'foo-bar'
```
---
#### `camel`
```hs
(str: T) => CamelCase<T>
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L88)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Transforms a variable name to camel case.
>
> Note: The rules for transforming anything to camel case are somewhat vague.
> So use this only for very simple names where the resulting value is
> absolutely unambiguous. For more examples of how names are transformed, have
> a look at the test cases.
>
#### Import
```ts
/* Node: */ import { camel } from "froebel/case";
/* Deno: */ import { camel } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
#### Example
```ts
camel('foo_bar') // 'fooBar'
```
---
#### `pascal`
```hs
(str: T) => Capitalize
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L109)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Transforms a variable name to pascal case.
>
> Note: The rules for transforming anything to pascal case are somewhat vague.
> So use this only for very simple names where the resulting value is
> absolutely unambiguous. For more examples of how names are transformed, have
> a look at the test cases.
>
#### Import
```ts
/* Node: */ import { pascal } from "froebel/case";
/* Deno: */ import { pascal } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
#### Example
```ts
pascal('foo_bar') // 'FooBar'
```
---
#### `screamingSnake`
```hs
(str: T) => Uppercase
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L122)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Transforms a variable name to screaming snake case.
>
> <sub>see [snake](#snake)</sub>
#### Import
```ts
/* Node: */ import { screamingSnake } from "froebel/case";
/* Deno: */ import { screamingSnake } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
#### Example
```ts
screamingSnake('fooBar') // 'FOO_BAR'
```
---
#### `transformCase`
```hs
(str: T, targetCase: C) => DelimitedCase<T, "_">
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/case.ts#L135)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/case.test.ts)_</sup></sup>
> Transform a variable name to `targetCase`
>
> <sub>see [snake](#snake), [kebab](#kebab), [camel](#camel), [pascal](#pascal), and [screamingSnake](#screamingsnake)</sub>
#### Import
```ts
/* Node: */ import { transformCase } from "froebel/case";
/* Deno: */ import { transformCase } from "https://deno.land/x/froebel@v0.23.2/case.ts";
```
## Math
#### `clamp`
```hs
(min: number, num: number, max: number) => number
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/clamp.ts#L2)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/clamp.test.ts)_</sup></sup>
> Clamp `num` between `min` and `max` inclusively.
#### Import
```ts
/* Node: */ import clamp from "froebel/clamp";
/* Deno: */ import clamp from "https://deno.land/x/froebel@v0.23.2/clamp.ts";
```
## Data Structures
#### `BiMap`
```hs
class BiMap<L, R>(data?: Map<L, R> | [L, R][], aliasLeft?: AL, aliasRight?: AR)
```
<sup><sup>_[source](https://github.com/MathisBullinger/froebel/blob/main/bimap.ts#L172)_ | _[tests](https://github.com/MathisBullinger/froebel/blob/main/bimap.test.ts)_</sup></sup>
> Bidirectional map. Maps two sets of keys in a one-to-one relation.
>
> Both sides are accessible (at .left & .right, or at their respective alias if
> one was provided in the constructor) with an interface similar to that of the
> built-in Map and the same iteration behavior.
>
#### Impor