const sleep = (ms: number): Promise => { return new Promise((resolve) => setTimeout(resolve, ms)); }; type MaybePromise = T | Promise; type TaskFunction = ( ...args: { [K in keyof TArgs]: MaybePromise } ) => Promise; const task = ( fn: (...args: TArgs) => Promise ): TaskFunction => { return async (...args) => { const resolved = await Promise.all(args); resolved satisfies TArgs; return await fn(...resolved); }; }; type SerialFunction = ( ...args: TArgs ) => Promise; const serial = ( fn: (...args: TArgs) => Promise ): SerialFunction => { let held: Promise | undefined; return async (...args) => { const { promise, resolve } = Promise.withResolvers(); const previous = held; held = promise; await previous; try { return await fn(...args); } finally { resolve(); } }; }; const e = task(async (a: number, c: number, d: number) => { await sleep(10); console.log("e: computing", a, "*", c, "*", d); return a * c * d; }); const d = task(async (b: number) => { await sleep(1); console.log("d: computing", b, "* 2"); return b * 2; }); const c = task(async (a: number, b: number) => { await sleep(5); console.log("c: computing", a, "+", b); return a + b; }); const a = task(async (n1: number, n2: number, n3: number) => { await sleep(15); console.log("a: computing", n1, "+", n2, "+", n3); return n1 + n2 + n3; }); const b = task(async (n1: number, n2: number, n3: number) => { await sleep(10); console.log("b: computing", n1, "+", n2, "+", n3); return n1 + n2 + n3; }); { const tA = a(4, 2, 3); const tB = b(4, 2, 3); const tC = c(tA, tB); const tD = d(tB); const tE = e(tA, tC, tD); const result = await tE; console.log(result); } export {};