Skip to content

Instantly share code, notes, and snippets.

@Xananax
Created July 13, 2017 22:41
Show Gist options
  • Save Xananax/4267a171a5728a9b29fa14a0f852cef2 to your computer and use it in GitHub Desktop.
Save Xananax/4267a171a5728a9b29fa14a0f852cef2 to your computer and use it in GitHub Desktop.
Typescript Typed Variadic Fold/Compose
export type Transformer<I,O> = (val:I)=>O
export type Promisable<I,O> = (val:I) => Promise<O>
export function composeSync<A,B>(a:Transformer<A,B>):(val:A)=>B
export function composeSync<A,B,C>(a:Transformer<A,B>,b:Transformer<B,C>):(val:A)=>C
export function composeSync<A,B,C,D>(a:Transformer<A,B>,b:Transformer<B,C>,c:Transformer<C,D>):(val:A)=>D
export function composeSync<A,B,C,D,E>(a:Transformer<A,B>,b:Transformer<B,C>,c:Transformer<C,D>,d:Transformer<D,E>):(val:A)=>E
export function composeSync<A,B,C,D,E,F>(a:Transformer<A,B>,b:Transformer<B,C>,c:Transformer<C,D>,d:Transformer<D,E>,e:Transformer<E,F>):(val:A)=>F
export function composeSync<A,B,C,D,E,F,G>(a:Transformer<A,B>,b:Transformer<B,C>,c:Transformer<C,D>,d:Transformer<D,E>,e:Transformer<E,F>,f:Transformer<F,G>):(val:A)=>G
export function composeSync<A,B,C,D,E,F,G,H>(a:Transformer<A,B>,b:Transformer<B,C>,c:Transformer<C,D>,d:Transformer<D,E>,e:Transformer<E,F>,f:Transformer<F,G>,g:Transformer<G,H>):(val:A)=>H
export function composeSync<A,B,C,D,E,F,G,H,I>(a:Transformer<A,B>,b:Transformer<B,C>,c:Transformer<C,D>,d:Transformer<D,E>,e:Transformer<E,F>,f:Transformer<F,G>,g:Transformer<G,H>,h:Transformer<H,I>):(val:A)=>I
export function composeSync<A,B,C,D,E,F,G,H,I,J>(a:Transformer<A,B>,b:Transformer<B,C>,c:Transformer<C,D>,d:Transformer<D,E>,e:Transformer<E,F>,f:Transformer<F,G>,g:Transformer<G,H>,h:Transformer<H,I>,i:Transformer<I,J>):(val:A)=>J
export function composeSync<I>(...funcs:Transformer<I,I>[]):(val:I)=>I
export function composeSync(...funcs:Transformer<any,any>[])
{ const composed =
( val:any ) =>
( funcs.reduce
( ( acc, fn ) =>
( fn(acc) )
, val
)
)
; return composed
}
export function composeAsync<A,B>(a:Promisable<A,B>):(val:A)=>Promise<B>
export function composeAsync<A,B,C>(a:Promisable<A,B>,b:Promisable<B,C>):(val:A)=>Promise<C>
export function composeAsync<A,B,C,D>(a:Promisable<A,B>,b:Promisable<B,C>,c:Promisable<C,D>):(val:A)=>Promise<D>
export function composeAsync<A,B,C,D,E>(a:Promisable<A,B>,b:Promisable<B,C>,c:Promisable<C,D>,d:Promisable<D,E>):(val:A)=>Promise<E>
export function composeAsync<A,B,C,D,E,F>(a:Promisable<A,B>,b:Promisable<B,C>,c:Promisable<C,D>,d:Promisable<D,E>,e:Promisable<E,F>):(val:A)=>Promise<F>
export function composeAsync<A,B,C,D,E,F,G>(a:Promisable<A,B>,b:Promisable<B,C>,c:Promisable<C,D>,d:Promisable<D,E>,e:Promisable<E,F>,f:Promisable<F,G>):(val:A)=>Promise<G>
export function composeAsync<A,B,C,D,E,F,G,H>(a:Promisable<A,B>,b:Promisable<B,C>,c:Promisable<C,D>,d:Promisable<D,E>,e:Promisable<E,F>,f:Promisable<F,G>,g:Promisable<G,H>):(val:A)=>Promise<H>
export function composeAsync<A,B,C,D,E,F,G,H,I>(a:Promisable<A,B>,b:Promisable<B,C>,c:Promisable<C,D>,d:Promisable<D,E>,e:Promisable<E,F>,f:Promisable<F,G>,g:Promisable<G,H>,h:Promisable<H,I>):(val:A)=>Promise<I>
export function composeAsync<A,B,C,D,E,F,G,H,I,J>(a:Promisable<A,B>,b:Promisable<B,C>,c:Promisable<C,D>,d:Promisable<D,E>,e:Promisable<E,F>,f:Promisable<F,G>,g:Promisable<G,H>,h:Promisable<H,I>,i:Promisable<I,J>):(val:A)=>Promise<J>
export function composeAsync<I>(...funcs:Transformer<I,I>[]):(val:I)=>Promise<I>
export function composeAsync<I>(...funcs:Promisable<I,I>[]):(val:I)=>Promise<I>
export function composeAsync(...funcs:Promisable<any,any>[])
{ const composed =
(val:any) =>
( funcs.reduce
( ( p, fn ) =>
( p.then(fn) )
, Promise.resolve(val)
)
)
; return composed
}
export const compose = (async:boolean=false) => async ? composeAsync : composeSync
/* testing stuff * /
const num_to_num = (a:number)=>a+1
const str_to_str = (a:string)=>a+"sdfsdf"
const num_to_str = (a:number)=>a+'sdfdsf'
const composed_num_to_num = composeSync(num_to_num,num_to_num) // num => num
const composed_str = composeSync(str_to_str) // str => str
//const composed_num_to_error = composeSync(num_to_num,str_to_str) // error!
const composed_num_to_str = composeSync(num_to_num,num_to_str,str_to_str) // num => str
const num_to_num_p = (a:number)=>Promise.resolve(a+1)
const str_to_str_p = (a:string)=>Promise.resolve(a+"sdfsdf")
const num_to_str_p = (a:number)=>Promise.resolve(a+'sdfdsf')
const composed_num_to_num_p = composeAsync(num_to_num_p,num_to_num_p) // num => num
const composed_str_p = composeSync(str_to_str_p) // str => str
//const composed_num_to_error_p = composeAsync(num_to_num_p,str_to_str_p) // error!
const composed_num_to_str_p = composeAsync(num_to_num_p,num_to_str_p,str_to_str_p) // num => str
/**/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment