export type Cache = Map; export function withCache) => T>( fn: U, cache: Cache, ): (key: unknown, ...args: Parameters) => T { return (key, ...args) => { if (cache.has(key)) { return cache.get(key) as T; } const value = fn(...args); cache.set(key, value); return value; }; } export function withCacheAsync< T, U extends (...args: Parameters) => Promise, >( fn: U, cache: Cache>, ): (key: unknown, ...args: Parameters) => Promise { return async (key, ...args) => { if (cache.has(key)) { return (await cache.get(key)) as T; } const value = fn(...args); cache.set(key, value); return await value; }; } export function memoize(fn: (arg: U) => T): [(arg: U) => T, Cache] { const cache = new Map(); const callback = withCache(fn, cache); return [ (arg) => { return callback(arg, arg); }, cache, ]; }