import areInputsEqual from './are-inputs-equal'; export type EqualityFn any> = ( newArgs: Parameters, lastArgs: Parameters, ) => boolean; export type MemoizedFn any> = { clear: () => void; (this: ThisParameterType, ...args: Parameters): ReturnType; }; // internal type type Cache any> = { lastThis: ThisParameterType; lastArgs: Parameters; lastResult: ReturnType; }; function memoizeOne any>( resultFn: TFunc, isEqual: EqualityFn = areInputsEqual, ): MemoizedFn { let cache: Cache | null = null; // breaking cache when context (this) or arguments change function memoized( this: ThisParameterType, ...newArgs: Parameters ): ReturnType { if (cache && cache.lastThis === this && isEqual(newArgs, cache.lastArgs)) { return cache.lastResult; } // Throwing during an assignment aborts the assignment: https://codepen.io/alexreardon/pen/RYKoaz // Doing the lastResult assignment first so that if it throws // the cache will not be overwritten const lastResult = resultFn.apply(this, newArgs); cache = { lastResult, lastArgs: newArgs, lastThis: this, }; return lastResult; } // Adding the ability to clear the cache of a memoized function memoized.clear = function clear() { cache = null; }; return memoized; } export default memoizeOne;