Files
tools/core/stdlib/src/functions/memoize/index.ts
T
robonen 96f4cba4a8 feat(stdlib): new modules + eslint/tsconfig migration
- Add array/async/etc. modules and type tests; migrate to eslint flat config
  and composite tsconfig (vitest typecheck enabled).
- Fix PubSub.emit to snapshot listeners before iterating (stable EventEmitter
  semantics; avoids invoking listeners added during the same emit).
2026-06-07 16:29:08 +07:00

51 lines
1.5 KiB
TypeScript

import type { AnyFunction } from '../../types';
export type MemoizeResolver<T extends AnyFunction> = (...args: Parameters<T>) => unknown;
export type MemoizedFunction<T extends AnyFunction> = T & {
/** The underlying cache, keyed by the resolver (first argument by default). */
cache: Map<unknown, ReturnType<T>>;
/** Drop all cached results. */
clear: () => void;
};
/**
* @name memoize
* @category Functions
* @description Caches the result of a function by its arguments
*
* @param {Function} fn - The function to memoize
* @param {Function} [resolver] - Maps the arguments to a cache key; defaults to the first argument
* @returns {MemoizedFunction} The memoized function, exposing its `cache` and a `clear()` method
*
* @example
* const slow = memoize((n: number) => expensive(n));
* slow(2); // computed
* slow(2); // cached
*
* @example
* const sum = memoize((a: number, b: number) => a + b, (a, b) => `${a},${b}`);
*
* @since 0.0.10
*/
export function memoize<T extends AnyFunction>(fn: T, resolver?: MemoizeResolver<T>): MemoizedFunction<T> {
const cache = new Map<unknown, ReturnType<T>>();
const memoized = function (this: unknown, ...args: Parameters<T>): ReturnType<T> {
const key = resolver ? resolver(...args) : args[0];
if (cache.has(key))
return cache.get(key)!;
const result = fn.apply(this, args) as ReturnType<T>;
cache.set(key, result);
return result;
} as MemoizedFunction<T>;
memoized.cache = cache;
memoized.clear = () => cache.clear();
return memoized;
}