Skip to content

Instantly share code, notes, and snippets.

@SET001
Created June 6, 2019 22:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SET001/c15a49b7d0ce28da615ba7d3c7e51f84 to your computer and use it in GitHub Desktop.
Save SET001/c15a49b7d0ce28da615ba7d3c7e51f84 to your computer and use it in GitHub Desktop.
// tslint:disable
export type UnpackPromise<T> = T extends Promise<Array<infer U>> ? U[] : T extends Promise<infer D> ? D : T;
type DeltaFn<ARG extends any[], R> = (...args: UnpackPromise<ARG>) => R | PromiseLike<R>;
type RiverFn<ARG, R> = (arg: UnpackPromise<ARG>) => R | PromiseLike<R>;
function pipe<A extends any[]>(): (...args: A) => UnpackPromise<A>;
function pipe<A extends any[], R1>(f1: DeltaFn<A, R1>): (...args: A) => Promise<R1>;
function pipe<A extends any[], R1, R2>(f1: DeltaFn<A, R1>, f2: RiverFn<R1, R2>): (...args: A) => Promise<R2>;
function pipe<A extends any[], R1, R2, R3>(
f1: DeltaFn<A, R1>,
f2: RiverFn<R1, R2>,
f3: RiverFn<R2, R3>
): (...args: A) => Promise<R3>;
function pipe<A extends any[], R1, R2, R3, R4>(
f1: DeltaFn<A, R1>,
f2: RiverFn<R1, R2>,
f3: RiverFn<R2, R3>,
f4: RiverFn<R3, R4>
): (...args: A) => Promise<R4>;
function pipe<A extends any[], R1, R2, R3, R4, R5>(
f1: DeltaFn<A, R1>,
f2: RiverFn<R1, R2>,
f3: RiverFn<R2, R3>,
f4: RiverFn<R3, R4>,
f5: RiverFn<R4, R5>
): (...args: A) => Promise<R5>;
function pipe<A extends any[], R1, R2, R3, R4, R5, R6>(
f1: DeltaFn<A, R1>,
f2: RiverFn<R1, R2>,
f3: RiverFn<R2, R3>,
f4: RiverFn<R3, R4>,
f5: RiverFn<R4, R5>,
f6: RiverFn<R5, R6>
): (...args: A) => Promise<R6>;
function pipe<A extends any[], R1, R2, R3, R4, R5, R6, R7>(
f1: DeltaFn<A, R1>,
f2: RiverFn<R1, R2>,
f3: RiverFn<R2, R3>,
f4: RiverFn<R3, R4>,
f5: RiverFn<R4, R5>,
f6: RiverFn<R5, R6>,
f7: RiverFn<R6, R7>
): (...args: A) => Promise<R7>;
function pipe<A extends any[], R1, R2, R3, R4, R5, R6, R7, R8>(
f1: DeltaFn<A, R1>,
f2: RiverFn<R1, R2>,
f3: RiverFn<R2, R3>,
f4: RiverFn<R3, R4>,
f5: RiverFn<R4, R5>,
f6: RiverFn<R5, R6>,
f7: RiverFn<R6, R7>,
f8: RiverFn<R7, R8>
): (...args: A) => Promise<R8>;
function pipe<A extends any[], R1, R2, R3, R4, R5, R6, R7, R8, R9>(
f1: DeltaFn<A, R1>,
f2: RiverFn<R1, R2>,
f3: RiverFn<R2, R3>,
f4: RiverFn<R3, R4>,
f5: RiverFn<R4, R5>,
f6: RiverFn<R5, R6>,
f7: RiverFn<R6, R7>,
f8: RiverFn<R7, R8>,
f9: RiverFn<R8, R9>
): (...args: A) => Promise<R9>;
function pipe<A extends any[], R1, R2, R3, R4, R5, R6, R7, R8, R9, R10>(
f1: DeltaFn<A, R1>,
f2: RiverFn<R1, R2>,
f3: RiverFn<R2, R3>,
f4: RiverFn<R3, R4>,
f5: RiverFn<R4, R5>,
f6: RiverFn<R5, R6>,
f7: RiverFn<R6, R7>,
f8: RiverFn<R7, R8>,
f9: RiverFn<R8, R9>,
f10: RiverFn<R9, R10>
): (...args: A) => Promise<R10>;
function pipe(deltaFn: DeltaFn<any, any>, ...riverFns: Array<RiverFn<any, any>>): (...args: any) => Promise<any>;
function pipe(...fns: any[]): any {
return (...initialArgs: any[]) =>
fns.reduce(
(pendingLastResult, fn, i) =>
pendingLastResult.then((lastResult: any) => {
// first iteration (lastResult is initialArgs), spread into delta function
const currentResult = i === 0 ? fn(...lastResult) : fn(lastResult);
return Array.isArray(currentResult) ? Promise.all(currentResult) : currentResult;
}),
Promise.all(initialArgs)
);
}
describe.only('pipe', () => {
it('should work', async () => {
const res = pipe(
 (n: number):number => n * 2,
 (s: string) => s.split(','),
)
console.log(await res(1))
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment