Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/jajaperson/copb

A functional composition framework built for TypesScript that provides type safety without the need for the usual countless overloads, thanks to some functional type trickery.
https://github.com/jajaperson/copb

composition currying functional-programming overloading pipes typescript

Last synced: about 1 month ago
JSON representation

A functional composition framework built for TypesScript that provides type safety without the need for the usual countless overloads, thanks to some functional type trickery.

Awesome Lists containing this project

README

        

# copb [![Version](https://img.shields.io/github/v/tag/jajaperson/copb?label=version)](https://github.com/jajaperson/copb/releases) [![Build Status](https://img.shields.io/github/workflow/status/jajaperson/copb/Test%20Deno%20Module)](https://github.com/jajaperson/copb/actions?query=workflow%3A%22Test+Deno+Module%22)

A functional composition helper for TypesScript that provides type safety
without the need for the usual countless overloads, thanks to some
functional type trickery.

This module contains just 4 curried functions: [`c`](#c), [`o`](#o), [`p`](#p), [`b`](#b).

## npm install

`copb` is available on [npm](https://npmjs.com/package/copb) as well as .

```sh
npm install --save copb
```

## The functions

### `b`

`b` is a simple curried **b**inary composition function, which the other
functions use under the hood.

```ts
import { b } from "https://deno.land/x/copb/mod.ts";

const f = (x: number) => x / 4;
const g = (x: number) => x - 5;

// h = f ∘ g
const h = b(f)(g);

console.log(h(13)); // -> 2
```

### `c`

`c` for **c**allable is used to build compositional stacks generated by `o` and
`p`. Once built, the resultant composed function can be applied in the normal
way. See usage in the sections below.

### `o`

`o` (named after the mathematical composition symbol) is for more complex
compositions, with the ability to compose any number of uniary functions
together.

```ts
import { b } from "https://deno.land/x/copb/mod.ts";

const f = (x: string) => "number " + x;
const g = (x: number) => String(x);
const h = (x: number) => x / 3;
const l = (x: number) => x - 6;

// m = f ∘ g ∘ h ∘ l
const m = c(o(f)(g)(h)(l));

console.log(m(15)); // -> "number 3"
```

### `p`

`p` for **p**ipeline is used to pipe the results of functions to each other. It is
identical to `o` except it is read from left to right.

```ts
import { b } from "https://deno.land/x/copb/mod.ts";

const f = (x: string) => "number " + x;
const g = (x: number) => String(x);
const h = (x: number) => x / 3;
const l = (x: number) => x - 6;

// m = f ∘ g ∘ h ∘ l
const m = c(p(l)(h)(g)(f));

console.log(m(15)); // -> "number 3"
```

## Usage notes

Applying a layer of abstraction, you can think of the `o` and `p` functions as
having _nodes_ within the compositional stack. Each of these nodes is denoted in
a seperate set of brackets.

```ts
c(o(node1)(node2)(node3));
```

When necessary, type annotations can be placed between nodes. For `o`, each
annotation somewhat counterintuitively represents the input type of the
following node, and the second annotation of the first node represents the final
result.

```ts
const m = c(o(f)(g)(h)(l));
```

For `p`, each annotation represents the output type of the following node, and
the second annotation of the first node represents the final input.

```ts
const m = c(p(l)(h)(g)(f));
```

## API

Generated API documentation, with pseudohaskell illustrations of type
signatures, is available
[here](https://doc.deno.land/https/deno.land/x/copb/mod.ts).

## Comments

### Intellisense

Your IDE will probably show a disgusting, monstrosity of a type signature.
That's because this project uses recursive types in order to provide robust type
safety. Type checking is still completely functional.