( target: (this: This, ...args: Args) => Return, context: ClassMemberDecoratorContext, )
| 14 | * @see https://en.wikipedia.org/wiki/Memoization |
| 15 | */ |
| 16 | export function memoize<This, Args extends unknown[], Return>( |
| 17 | target: (this: This, ...args: Args) => Return, |
| 18 | context: ClassMemberDecoratorContext, |
| 19 | ) { |
| 20 | if (context.kind !== 'method' && context.kind !== 'getter') { |
| 21 | throw new Error('Memoize decorator can only be used on methods or get accessors.'); |
| 22 | } |
| 23 | |
| 24 | const cache = new Map<string, Return>(); |
| 25 | |
| 26 | return function (this: This, ...args: Args): Return { |
| 27 | for (const arg of args) { |
| 28 | if (!isJSONSerializable(arg)) { |
| 29 | throw new Error( |
| 30 | `Argument ${isNonPrimitive(arg) ? arg.toString() : arg} is JSON serializable.`, |
| 31 | ); |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | const key = JSON.stringify(args); |
| 36 | if (cache.has(key)) { |
| 37 | return cache.get(key) as Return; |
| 38 | } |
| 39 | |
| 40 | const result = target.apply(this, args); |
| 41 | cache.set(key, result); |
| 42 | |
| 43 | return result; |
| 44 | }; |
| 45 | } |
| 46 | |
| 47 | /** Method to check if value is a non primitive. */ |
| 48 | function isNonPrimitive(value: unknown): value is object | Function | symbol { |
nothing calls this directly
no test coverage detected