Skip to content

Instantly share code, notes, and snippets.

@zyishai
Last active December 11, 2024 16:28
Show Gist options
  • Save zyishai/40bea28cbe7820c46b2f83ae5b4719b8 to your computer and use it in GitHub Desktop.
Save zyishai/40bea28cbe7820c46b2f83ae5b4719b8 to your computer and use it in GitHub Desktop.
TypeScript Combinators

Summary

This RFC proposes a library of point-free functional combinators in TypeScript that leverage native TypeScript types. By reinterpreting existing types (null, undefined, never, arrays, etc.) in a functional context, we can build a lightweight, non-intrusive API that integrates seamlessly with existing TypeScript codebases.

Maybe

A Maybe type in ts-combinators is a regular TypeScript type, such as: Number, String, Boolean etc that is defined as follows:

type Empty = null | undefined | void | never;
type Maybe<T> = T | Empty;

A maybe is any value that is not null, undefined, or void. ts-combinators allows to interact with maybe values with the some or none combinators:

const addOne = pipe(
  some((n: number) => n + 1),
  none(constant(0))
);

const five = addOne(4); // returns 5
const zero = addOne(null);  // returns 0

The combinator constant returns a delayed value (i.e., function that accepts void and returns some value).

Either

An Either type is any function that returns a two-items array, where the first item is the Left value, usually represents an error, and the second item is the Right value, usually represents a successful result:

type Either<L, R> = () => [L, undefined] | [undefined, R];

The following combinators work with an Either type:

  • right maps a right value, if the either is of the Right variant.
  • left maps a left value, if the either is of the Left variant.
  • chainRight maps a right value, returns a new Either.
  • extract returns the value of the Either (the value that is not undefined).

IO

The IO type represents a delayed computation:

// add :: Number -> Number -> Number
const add = (a: number) => (b: number) => a + b;

// ioAdd :: Number -> Number -> Void -> Number
const ioAdd = io(add);

// Example usage:
const run = ioAdd(2)(3); // returned type: `() => number`;
console.log(run()); // prints `5`

Array

ts-combinators does not introduce a new type for arrays; Instead, it implements point-free combinators to work with arrays:

  • mapArr applies a functor to every item of the array.
  • filterArr filters the array based on the provided predicate.
  • reduceArr accepts a curried reducer function, and an initial value. Returns the aggregated result of applying the reducer function to every item of the array.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment