# @helpers4/function

> Tree-shakable TypeScript utility functions for the `function` domain.
> Package: `@helpers4/function` — Version: 2.0.0
> License: LGPL-3.0-or-later

## Installation

```sh
npm install @helpers4/function
# or
pnpm add @helpers4/function
```

## Usage

```typescript
import { compose, curry, debounce, ... } from '@helpers4/function';
```

## Functions

| Function | Description |
|---|---|
| `compose` | Composes functions right-to-left: `compose(f, g)(x)` is equivalent to `f(g(x))`.  The inverse of pip |
| `curry` | Transforms a multi-argument function into a chain of single-argument functions (Haskell-style curryi |
| `debounce` | Creates a debounced function that delays invoking func until after delay milliseconds have elapsed s |
| `flip` | Creates a function that invokes `fn` with the first two arguments swapped.  Useful when adapting a f |
| `identity` | Returns the given value unchanged  Useful as a default transform, in function composition, or as a p |
| `memoize` | Returns a memoized version of the function that caches results |
| `negate` | Creates a function that negates the result of `predicate`. |
| `noop` | A no-operation function that does nothing and returns `undefined`  Useful as a default callback, pla |
| `once` | Creates a function that is restricted to be called only once. Subsequent calls return the cached res |
| `partial` | Partially applies arguments to a function, returning a new function that accepts the remaining argum |
| `pipe` | Composes functions left-to-right: the output of each function is passed as input to the next.  The i |
| `returnOrThrowError` | Return a value or throw an error if null or undefined. |
| `throttle` | Creates a throttled function that only invokes func at most once per every wait milliseconds |

---

## API Reference

### `compose`

Composes functions right-to-left: `compose(f, g)(x)` is equivalent to `f(g(x))`.

The inverse of pipe, which applies functions left-to-right.

```typescript
import { compose } from '@helpers4/function';

compose<A, B>(fn1: function): function
```

**Parameters:**

- `fn1: function`

**Returns:** `function` — A function that applies `fns` in reverse order

```typescript
import { compose } from '@helpers4/function';

compose<A, B, C>(fn2: function, fn1: function): function
```

**Parameters:**

- `fn2: function`
- `fn1: function`

**Returns:** `function` — A function that applies `fns` in reverse order

```typescript
import { compose } from '@helpers4/function';

compose<A, B, C, D>(fn3: function, fn2: function, fn1: function): function
```

**Parameters:**

- `fn3: function`
- `fn2: function`
- `fn1: function`

**Returns:** `function` — A function that applies `fns` in reverse order

```typescript
import { compose } from '@helpers4/function';

compose<A, B, C, D, E>(fn4: function, fn3: function, fn2: function, fn1: function): function
```

**Parameters:**

- `fn4: function`
- `fn3: function`
- `fn2: function`
- `fn1: function`

**Returns:** `function` — A function that applies `fns` in reverse order

```typescript
import { compose } from '@helpers4/function';

compose<A, B, C, D, E, F>(fn5: function, fn4: function, fn3: function, fn2: function, fn1: function): function
```

**Parameters:**

- `fn5: function`
- `fn4: function`
- `fn3: function`
- `fn2: function`
- `fn1: function`

**Returns:** `function` — A function that applies `fns` in reverse order

```typescript
import { compose } from '@helpers4/function';

compose<A, B, C, D, E, F, G>(fn6: function, fn5: function, fn4: function, fn3: function, fn2: function, fn1: function): function
```

**Parameters:**

- `fn6: function`
- `fn5: function`
- `fn4: function`
- `fn3: function`
- `fn2: function`
- `fn1: function`

**Returns:** `function` — A function that applies `fns` in reverse order

```typescript
import { compose } from '@helpers4/function';

compose<A, B, C, D, E, F, G, H>(fn7: function, fn6: function, fn5: function, fn4: function, fn3: function, fn2: function, fn1: function): function
```

**Parameters:**

- `fn7: function`
- `fn6: function`
- `fn5: function`
- `fn4: function`
- `fn3: function`
- `fn2: function`
- `fn1: function`

**Returns:** `function` — A function that applies `fns` in reverse order

```typescript
import { compose } from '@helpers4/function';

compose<A, B, C, D, E, F, G, H, I>(fn8: function, fn7: function, fn6: function, fn5: function, fn4: function, fn3: function, fn2: function, fn1: function): function
```

**Parameters:**

- `fn8: function`
- `fn7: function`
- `fn6: function`
- `fn5: function`
- `fn4: function`
- `fn3: function`
- `fn2: function`
- `fn1: function`

**Returns:** `function` — A function that applies `fns` in reverse order

**Examples:**

*Compose functions right-to-left*

`compose(f, g)(x)` is equivalent to `f(g(x))`. The rightmost function is applied first.

```typescript
const process = compose(
  String,
  (x: number) => x * 2,
  (x: number) => x + 1
);
process(3); // => "8"
```

*Build a validator from small predicates*

Compose small predicate functions into a single validator.

```typescript
const validate = compose(
  (ok: boolean) => ok || (() => { throw new Error('invalid'); })(),
  (s: string) => s.length >= 3
);
validate('ab');  // throws
validate('abc'); // => true
```

---

### `curry`

Transforms a multi-argument function into a chain of single-argument functions
(Haskell-style currying). Supports up to 5 arguments.

The inverse operation of applying all arguments at once:
`curry(fn)(a)(b)` is equivalent to `fn(a, b)`.

```typescript
import { curry } from '@helpers4/function';

curry<A, R>(fn: function): function
```

**Parameters:**

- `fn: function` — The function to curry

**Returns:** `function` — A curried version of `fn`

```typescript
import { curry } from '@helpers4/function';

curry<A, B, R>(fn: function): function
```

**Parameters:**

- `fn: function` — The function to curry

**Returns:** `function` — A curried version of `fn`

```typescript
import { curry } from '@helpers4/function';

curry<A, B, C, R>(fn: function): function
```

**Parameters:**

- `fn: function` — The function to curry

**Returns:** `function` — A curried version of `fn`

```typescript
import { curry } from '@helpers4/function';

curry<A, B, C, D, R>(fn: function): function
```

**Parameters:**

- `fn: function` — The function to curry

**Returns:** `function` — A curried version of `fn`

```typescript
import { curry } from '@helpers4/function';

curry<A, B, C, D, E, R>(fn: function): function
```

**Parameters:**

- `fn: function` — The function to curry

**Returns:** `function` — A curried version of `fn`

**Examples:**

*Create reusable adder*

Curry a 2-argument function to build specialised versions.

```typescript
const add = curry((a: number, b: number) => a + b);
const add5 = add(5);

add5(3);  // => 8
add5(10); // => 15
```

*Pipeline-friendly 3-argument function*

Curry enables point-free style when composing pipelines.

```typescript
const clamp = curry((min: number, max: number, v: number) =>
  Math.min(Math.max(v, min), max)
);
const clamp0to100 = clamp(0)(100);

clamp0to100(42);  // => 42
clamp0to100(-5);  // => 0
clamp0to100(150); // => 100
```

---

### `debounce`

Creates a debounced function that delays invoking func until after delay milliseconds have elapsed since the last time the debounced function was invoked

```typescript
import { debounce } from '@helpers4/function';

debounce<A extends unknown[], R>(func: function, delay: number): function
```

**Parameters:**

- `func: function` — The function to debounce
- `delay: number` — The number of milliseconds to delay

**Returns:** `function` — The debounced function

**Examples:**

*Debounce a function*

The debounced function is only called once after the delay, even if invoked multiple times.

```typescript
const fn = debounce((x: number) => console.log(x), 100);
fn(1);
fn(2);
fn(3);
// Only logs 3 after 100ms
```

---

### `flip`

Creates a function that invokes `fn` with the first two arguments swapped.

Useful when adapting a function for use in higher-order pipelines where the
argument order is reversed (e.g. passing a binary callback to `reduce`).

```typescript
import { flip } from '@helpers4/function';

flip<A, B, Rest extends unknown[], R>(fn: function): function
```

**Parameters:**

- `fn: function` — The function to wrap.

**Returns:** `function` — A new function with the first two parameters swapped.

**Examples:**

*Swap argument order*

Returns a new function where the first two arguments are swapped.

```typescript
const sub = (a: number, b: number) => a - b;
flip(sub)(3, 10); // => 7  (10 - 3)
```

*Adapt a divide function*

Useful for adapting binary callbacks in higher-order functions.

```typescript
const divide = (a: number, b: number) => a / b;
const divideInto = flip(divide);
divideInto(2, 100); // => 50
```

---

### `identity`

Returns the given value unchanged

Useful as a default transform, in function composition, or as a placeholder mapper.

```typescript
import { identity } from '@helpers4/function';

identity<T>(value: T): T
```

**Parameters:**

- `value: T` — The value to return

**Returns:** `T` — The same value

**Examples:**

*Return a primitive unchanged*

The value is returned as-is with its type preserved.

```typescript
identity(42);       // 42
identity('hello');  // 'hello'
identity(true);     // true
```

*Use as a default mapper*

Pass identity where a transform function is required but no transformation is needed.

```typescript
[1, 2, 3].map(identity); // [1, 2, 3]
```

---

### `memoize`

Returns a memoized version of the function that caches results

```typescript
import { memoize } from '@helpers4/function';

memoize<A extends unknown[], R>(func: function): function
```

**Parameters:**

- `func: function` — The function to memoize

**Returns:** `function` — The memoized function

**Examples:**

*Cache function results*

The underlying function is only called once for the same arguments.

```typescript
let calls = 0;
const expensive = memoize((n: number) => { calls++; return n * 2; });
expensive(5); // => 10 (computed)
expensive(5); // => 10 (cached)
```

---

### `negate`

Creates a function that negates the result of `predicate`.

```typescript
import { negate } from '@helpers4/function';

negate<T extends unknown[]>(predicate: function): function
```

**Parameters:**

- `predicate: function` — A predicate function returning a boolean.

**Returns:** `function` — A new function that returns the logical negation of `predicate`.

**Examples:**

*Derive isOdd from isEven*

Returns a function that inverts the boolean result of the given predicate.

```typescript
const isEven = (n: number) => n % 2 === 0;
const isOdd = negate(isEven);
isOdd(3); // => true
isOdd(4); // => false
```

*Use as a filter predicate*

negate is ideal for inverting predicates passed to Array.filter.

```typescript
const isEmpty = (arr: unknown[]) => arr.length === 0;
[[], [1], [], [2, 3]].filter(negate(isEmpty))
// => [[1], [2, 3]]
```

---

### `noop`

A no-operation function that does nothing and returns `undefined`

Useful as a default callback, placeholder, or to explicitly ignore a value.

```typescript
import { noop } from '@helpers4/function';

noop(): void
```

**Returns:** `void` — Nothing (`undefined`)

**Examples:**

*Use as a default callback*

Replace an optional callback with noop to avoid null checks.

```typescript
const onComplete = options.callback ?? noop;
onComplete(); // does nothing
```

*Silence an event handler*

Pass noop wherever a function is required but no action is needed.

```typescript
element.addEventListener('click', noop);
```

---

### `once`

Creates a function that is restricted to be called only once.
Subsequent calls return the cached result of the first invocation.

The returned function exposes a `.reset()` method to clear the cache and
allow the original function to be called again.

```typescript
import { once } from '@helpers4/function';

once<A extends unknown[], R>(fn: function): OnceFn<A, R>
```

**Parameters:**

- `fn: function` — The function to wrap

**Returns:** `OnceFn<A, R>` — A function that invokes `fn` at most once, with a `.reset()` method

**Examples:**

*Run expensive setup only once*

The wrapped function executes only on the first call; all subsequent calls return the cached result.

```typescript
const init = once(() => ({ config: 'loaded' }));

const a = init(); // runs the function
const b = init(); // returns cached result
a === b; // => true

init.reset(); // clear cache
const c = init(); // runs the function again
a === c; // => false (new object)
```

*Guard against multiple event-listener registrations*

Ensure a side-effecting setup (e.g. addEventListener) runs at most once.

```typescript
const register = once((el: HTMLElement) => {
  el.addEventListener('click', handler);
});

register(button); // registers handler
register(button); // no-op — handler already registered
```

---

### `partial`

Partially applies arguments to a function, returning a new function that
accepts the remaining arguments.

```typescript
import { partial } from '@helpers4/function';

partial<A, R>(fn: function, a: A): function
```

**Parameters:**

- `fn: function` — The function to partially apply
- `a: A`

**Returns:** `function` — A function waiting for the remaining arguments

```typescript
import { partial } from '@helpers4/function';

partial<A, B, R>(fn: function, a: A): function
```

**Parameters:**

- `fn: function` — The function to partially apply
- `a: A`

**Returns:** `function` — A function waiting for the remaining arguments

```typescript
import { partial } from '@helpers4/function';

partial<A, B, C, R>(fn: function, a: A): function
```

**Parameters:**

- `fn: function` — The function to partially apply
- `a: A`

**Returns:** `function` — A function waiting for the remaining arguments

```typescript
import { partial } from '@helpers4/function';

partial<A, B, C, R>(fn: function, a: A, b: B): function
```

**Parameters:**

- `fn: function` — The function to partially apply
- `a: A`
- `b: B`

**Returns:** `function` — A function waiting for the remaining arguments

```typescript
import { partial } from '@helpers4/function';

partial<A, B, C, D, R>(fn: function, a: A): function
```

**Parameters:**

- `fn: function` — The function to partially apply
- `a: A`

**Returns:** `function` — A function waiting for the remaining arguments

```typescript
import { partial } from '@helpers4/function';

partial<A, B, C, D, R>(fn: function, a: A, b: B): function
```

**Parameters:**

- `fn: function` — The function to partially apply
- `a: A`
- `b: B`

**Returns:** `function` — A function waiting for the remaining arguments

```typescript
import { partial } from '@helpers4/function';

partial<A, B, C, D, R>(fn: function, a: A, b: B, c: C): function
```

**Parameters:**

- `fn: function` — The function to partially apply
- `a: A`
- `b: B`
- `c: C`

**Returns:** `function` — A function waiting for the remaining arguments

**Examples:**

*Create a specialised multiplier*

Pre-fill the first argument to derive a specialised function.

```typescript
const multiply = (a: number, b: number) => a * b;
const double = partial(multiply, 2);
const triple = partial(multiply, 3);

double(5); // => 10
triple(5); // => 15
```

*Pre-fill multiple arguments*

Supply several arguments up front, leaving only the last one open.

```typescript
const format = (prefix: string, sep: string, value: string) =>
  `${prefix}${sep}${value}`;

const withLabel = partial(format, 'Status', ': ');
withLabel('passing'); // => 'Status: passing'
```

---

### `pipe`

Composes functions left-to-right: the output of each function is passed as
input to the next.

The inverse of compose, which applies functions right-to-left.

```typescript
import { pipe } from '@helpers4/function';

pipe<A, B>(fn1: function): function
```

**Parameters:**

- `fn1: function`

**Returns:** `function` — A function that applies `fns` in order

```typescript
import { pipe } from '@helpers4/function';

pipe<A, B, C>(fn1: function, fn2: function): function
```

**Parameters:**

- `fn1: function`
- `fn2: function`

**Returns:** `function` — A function that applies `fns` in order

```typescript
import { pipe } from '@helpers4/function';

pipe<A, B, C, D>(fn1: function, fn2: function, fn3: function): function
```

**Parameters:**

- `fn1: function`
- `fn2: function`
- `fn3: function`

**Returns:** `function` — A function that applies `fns` in order

```typescript
import { pipe } from '@helpers4/function';

pipe<A, B, C, D, E>(fn1: function, fn2: function, fn3: function, fn4: function): function
```

**Parameters:**

- `fn1: function`
- `fn2: function`
- `fn3: function`
- `fn4: function`

**Returns:** `function` — A function that applies `fns` in order

```typescript
import { pipe } from '@helpers4/function';

pipe<A, B, C, D, E, F>(fn1: function, fn2: function, fn3: function, fn4: function, fn5: function): function
```

**Parameters:**

- `fn1: function`
- `fn2: function`
- `fn3: function`
- `fn4: function`
- `fn5: function`

**Returns:** `function` — A function that applies `fns` in order

```typescript
import { pipe } from '@helpers4/function';

pipe<A, B, C, D, E, F, G>(fn1: function, fn2: function, fn3: function, fn4: function, fn5: function, fn6: function): function
```

**Parameters:**

- `fn1: function`
- `fn2: function`
- `fn3: function`
- `fn4: function`
- `fn5: function`
- `fn6: function`

**Returns:** `function` — A function that applies `fns` in order

```typescript
import { pipe } from '@helpers4/function';

pipe<A, B, C, D, E, F, G, H>(fn1: function, fn2: function, fn3: function, fn4: function, fn5: function, fn6: function, fn7: function): function
```

**Parameters:**

- `fn1: function`
- `fn2: function`
- `fn3: function`
- `fn4: function`
- `fn5: function`
- `fn6: function`
- `fn7: function`

**Returns:** `function` — A function that applies `fns` in order

```typescript
import { pipe } from '@helpers4/function';

pipe<A, B, C, D, E, F, G, H, I>(fn1: function, fn2: function, fn3: function, fn4: function, fn5: function, fn6: function, fn7: function, fn8: function): function
```

**Parameters:**

- `fn1: function`
- `fn2: function`
- `fn3: function`
- `fn4: function`
- `fn5: function`
- `fn6: function`
- `fn7: function`
- `fn8: function`

**Returns:** `function` — A function that applies `fns` in order

**Examples:**

*Transform a value through a pipeline*

Functions are applied left-to-right; the output of each becomes the input of the next.

```typescript
const process = pipe(
  (x: number) => x + 1,
  (x: number) => x * 2,
  String
);
process(3); // => "8"
```

*Sanitise a string*

Chain string transforms left-to-right with pipe.

```typescript
const sanitize = pipe(
  (s: string) => s.trim(),
  (s: string) => s.toLowerCase(),
  (s: string) => s.replace(/\s+/g, '-')
);
sanitize('  Hello World  '); // => "hello-world"
```

---

### `returnOrThrowError`

Return a value or throw an error if null or undefined.

```typescript
import { returnOrThrowError } from '@helpers4/function';

returnOrThrowError<T>(value: T | null | undefined, error: string): T
```

**Parameters:**

- `value: T | null | undefined` — A possible non-defined value.
- `error: string` — The error message to throw.

**Returns:** `T` — A defined value or an error.

**Examples:**

*Return a defined value*

Returns the value when it is defined and not null.

```typescript
returnOrThrowError('hello', 'Value is missing')
// => 'hello'
```

*Throw on null*

Throws an error when the value is null or undefined.

```typescript
returnOrThrowError(null, 'Value is missing')
// throws Error('Value is missing')
```

---

### `throttle`

Creates a throttled function that only invokes func at most once per every wait milliseconds

```typescript
import { throttle } from '@helpers4/function';

throttle<A extends unknown[], R>(func: function, wait: number): function
```

**Parameters:**

- `func: function` — The function to throttle
- `wait: number` — The number of milliseconds to throttle invocations to

**Returns:** `function` — The throttled function

**Examples:**

*Throttle rapid calls*

The throttled function is invoked at most once per wait period.

```typescript
const fn = throttle(() => console.log('tick'), 100);
fn(); // executes immediately
fn(); // ignored (within wait period)
```

---
