type CoalescedInvoke = { isOrigin: boolean value: T } export type UnwrapPromise = T extends Promise ? U : T const globalInvokeCache = new Map>>() export function withCoalescedInvoke any>( func: F ): ( key: string, args: Parameters ) => Promise>>> { return async function (key: string, args: Parameters) { const entry = globalInvokeCache.get(key) if (entry) { return entry.then((res) => ({ isOrigin: false, value: res.value as UnwrapPromise>, })) } async function __wrapper() { return await func.apply(undefined, args) } const future = __wrapper() .then((res) => { globalInvokeCache.delete(key) return { isOrigin: true, value: res as UnwrapPromise> } }) .catch((err) => { globalInvokeCache.delete(key) return Promise.reject(err) }) globalInvokeCache.set(key, future) return future } }