Skip to content

Instantly share code, notes, and snippets.

@jordangarcia
Created April 12, 2025 01:38
Show Gist options
  • Save jordangarcia/7c0f39943dfa685408e11d53143faf56 to your computer and use it in GitHub Desktop.
Save jordangarcia/7c0f39943dfa685408e11d53143faf56 to your computer and use it in GitHub Desktop.
// Type for a value that might be a Promise
type MaybePromise<T> = T | Promise<T>;
// Async compose with proper type inference for up to 10 functions
function asyncCompose<A, B>(
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<B>;
function asyncCompose<A, B, C>(
bc: (b: B) => MaybePromise<C>,
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<C>;
function asyncCompose<A, B, C, D>(
cd: (c: C) => MaybePromise<D>,
bc: (b: B) => MaybePromise<C>,
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<D>;
function asyncCompose<A, B, C, D, E>(
de: (d: D) => MaybePromise<E>,
cd: (c: C) => MaybePromise<D>,
bc: (b: B) => MaybePromise<C>,
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<E>;
function asyncCompose<A, B, C, D, E, F>(
ef: (e: E) => MaybePromise<F>,
de: (d: D) => MaybePromise<E>,
cd: (c: C) => MaybePromise<D>,
bc: (b: B) => MaybePromise<C>,
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<F>;
function asyncCompose<A, B, C, D, E, F, G>(
fg: (f: F) => MaybePromise<G>,
ef: (e: E) => MaybePromise<F>,
de: (d: D) => MaybePromise<E>,
cd: (c: C) => MaybePromise<D>,
bc: (b: B) => MaybePromise<C>,
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<G>;
function asyncCompose<A, B, C, D, E, F, G, H>(
gh: (g: G) => MaybePromise<H>,
fg: (f: F) => MaybePromise<G>,
ef: (e: E) => MaybePromise<F>,
de: (d: D) => MaybePromise<E>,
cd: (c: C) => MaybePromise<D>,
bc: (b: B) => MaybePromise<C>,
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<H>;
function asyncCompose<A, B, C, D, E, F, G, H, I>(
hi: (h: H) => MaybePromise<I>,
gh: (g: G) => MaybePromise<H>,
fg: (f: F) => MaybePromise<G>,
ef: (e: E) => MaybePromise<F>,
de: (d: D) => MaybePromise<E>,
cd: (c: C) => MaybePromise<D>,
bc: (b: B) => MaybePromise<C>,
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<I>;
function asyncCompose<A, B, C, D, E, F, G, H, I, J>(
ij: (i: I) => MaybePromise<J>,
hi: (h: H) => MaybePromise<I>,
gh: (g: G) => MaybePromise<H>,
fg: (f: F) => MaybePromise<G>,
ef: (e: E) => MaybePromise<F>,
de: (d: D) => MaybePromise<E>,
cd: (c: C) => MaybePromise<D>,
bc: (b: B) => MaybePromise<C>,
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<J>;
function asyncCompose<A, B, C, D, E, F, G, H, I, J, K>(
jk: (j: J) => MaybePromise<K>,
ij: (i: I) => MaybePromise<J>,
hi: (h: H) => MaybePromise<I>,
gh: (g: G) => MaybePromise<H>,
fg: (f: F) => MaybePromise<G>,
ef: (e: E) => MaybePromise<F>,
de: (d: D) => MaybePromise<E>,
cd: (c: C) => MaybePromise<D>,
bc: (b: B) => MaybePromise<C>,
ab: (a: A) => MaybePromise<B>
): (a: A) => Promise<K>;
// Implementation that works for any number of functions
function asyncCompose(...fns: Array<(arg: any) => MaybePromise<any>>): (arg: any) => Promise<any> {
return async (x: any) => {
return fns.reduceRight(async (acc, fn) => fn(await acc), x);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment