Skip to content

Instantly share code, notes, and snippets.

@simlrh
Last active April 17, 2022 05:39
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simlrh/f8405a4879c2153fa8a3f4c7fd4cdb8f to your computer and use it in GitHub Desktop.
Save simlrh/f8405a4879c2153fa8a3f4c7fd4cdb8f to your computer and use it in GitHub Desktop.
Typescript compose and pipe "infix operators"
interface Composable<B,C> {
(b: B): C;
I: <D>(f: (c: C) => D) => Composable<B,D>;
o: <A>(f: (a: A) => B) => Composable<A,C>;
}
/*
* Non-type safe internal function - type safety of result is guaranteed by
* allowing creation only through `I` and `o` functions and methods
*/
function makeComposable<B,C>(fs: Array<(arg: any) => any>): Composable<B,C> {
const apply = (b: B) => fs.reduce((acc: any, f: (arg: any) => any) => f(acc), b);
apply.I = <D>(f: (c: C) => D) => makeComposable<B,D>([...fs, f]);
apply.o = <A>(f: (a: A) => B) => makeComposable<A,C>([f, ...fs]);
return apply;
}
export function I<A,B>(f: (a: A) => B): Composable<A,B> {
return makeComposable<A,B>([f]);
};
export const o = I;
// Usage
const double = (x: number) => x * 2;
const numToString = (x: number) => `${x}`;
const toCharacterArray = (x: string) => x.split('');
const joinWithDashes = (x: string[]) => x.join('-');
const myPipe = (
I (double)
.I (numToString)
.I (toCharacterArray)
.I (joinWithDashes)
.I (console.log)
);
myPipe(12345); // 2-4-6-9-0
const myComposition: (a: number) => void =
o(console.log). o (joinWithDashes). o (toCharacterArray). o (numToString). o (double);
myComposition(12345); // 2-4-6-9-0
@jltrem
Copy link

jltrem commented Apr 16, 2020

I found this tremendously helpful. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment