• Memoizes the result of a function, caching the results based on input arguments. It allows for optional custom key generation and custom cache management.

    The function will either compute the result or return the cached result if the same arguments were provided previously.

    Type Parameters

    • T extends (...args: any) => any

      The type of the function to memoize. It extends a function that takes any arguments and returns any type.

    Parameters

    • fn: T

      The function to memoize. This function will be invoked with the arguments, and its result will be cached.

    • OptionalkeyFn: (...args: Parameters<T>) => string

      Optional custom key generation function. If provided, it will be used to generate the cache key based on the function arguments. If not provided, the default key generator uses JSON.stringify to create a string key from the arguments.

    • OptionalcacheFactory: () => {
          get: (key: string) => undefined | ReturnType<T>;
          has: (key: string) => boolean;
          set: (key: string, value: ReturnType<T>) => void;
      }

      Optional factory function to create a custom cache. This allows users to supply their own caching mechanism (e.g., LRU cache) instead of the default Map object.

    Returns (...args: Parameters<T>) => ReturnType<T>

    A memoized version of the provided function. The returned function will either compute and cache the result or return the cached result if available.

    Throws an error if the provided fn is not a function, or if the keyFn (if provided) is not a function.

    const add = (a: number, b: number) => a + b;
    const memoizedAdd = memoize(add);
    memoizedAdd(1, 2); // computes and returns 3
    memoizedAdd(1, 2); // returns cached result: 3
    const customKeyFn = (a: number, b: number) => `${a}-${b}`;
    const memoizedAddWithCustomKey = memoize(add, customKeyFn);
    memoizedAddWithCustomKey(1, 2); // uses custom key '1-2' for caching
    const fn = (a: number) => a * 2

    // Custom LRU Cache implementation for example
    class LRUCache<V> {
    private cache: Map<string, V>
    private maxSize: number

    constructor(maxSize: number) {
    this.cache = new Map()
    this.maxSize = maxSize
    }

    get(key: string): V | undefined {
    const value = this.cache.get(key)
    if (value !== undefined) {
    this.cache.delete(key)
    this.cache.set(key, value)
    }
    return value
    }

    set(key: string, value: V): void {
    if (this.cache.has(key)) {
    this.cache.delete(key)
    }
    this.cache.set(key, value)
    if (this.cache.size > this.maxSize) {
    const firstKey = this.cache.keys().next().value
    if (firstKey !== undefined) {
    this.cache.delete(firstKey)
    }
    }
    }
    has(key: string): boolean {
    return this.cache.has(key)
    }
    }

    const memoizedFn = memoize(fn, undefined, () => new LRUCache<ReturnType<typeof fn>>(3)) // Max size of 3 items