memoize wraps a function in a Map-backed cache keyed by the JSON serialization of its arguments. Re-invocations with previously-seen arguments return the cached result instead of recomputing.
export function memoize<T extends (...args: unknown[]) => unknown>(fn: T): T {
const cache = new Map<string, ReturnType<T>>();
return ((...args: Parameters<T>): ReturnType<T> => {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key) as ReturnType<T>;
const result = fn(...args) as ReturnType<T>;
cache.set(key, result);
return result;
}) as T;
}
Caveats
- The cache key is
JSON.stringify(args). Non-serializable inputs (functions, symbols, circular structures) will throw or produce unstable keys. - There's no eviction policy here — the cache grows forever. For long-lived applications, consider an LRU strategy.
- Only safe for pure functions. Memoizing a function with side effects suppresses those side effects on cache hits.