|
13 | 13 | *
|
14 | 14 | * @see https://en.wikipedia.org/wiki/Memoization
|
15 | 15 | */
|
16 |
| -export function memoize<T>( |
17 |
| - target: Object, |
18 |
| - propertyKey: string | symbol, |
19 |
| - descriptor: TypedPropertyDescriptor<T>, |
20 |
| -): TypedPropertyDescriptor<T> { |
21 |
| - const descriptorPropertyName = descriptor.get ? 'get' : 'value'; |
22 |
| - const originalMethod: unknown = descriptor[descriptorPropertyName]; |
23 |
| - |
24 |
| - if (typeof originalMethod !== 'function') { |
| 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') { |
25 | 21 | throw new Error('Memoize decorator can only be used on methods or get accessors.');
|
26 | 22 | }
|
27 | 23 |
|
28 |
| - const cache = new Map<string, unknown>(); |
| 24 | + const cache = new Map<string, Return>(); |
29 | 25 |
|
30 |
| - return { |
31 |
| - ...descriptor, |
32 |
| - [descriptorPropertyName]: function (this: unknown, ...args: unknown[]) { |
33 |
| - for (const arg of args) { |
34 |
| - if (!isJSONSerializable(arg)) { |
35 |
| - throw new Error( |
36 |
| - `Argument ${isNonPrimitive(arg) ? arg.toString() : arg} is JSON serializable.`, |
37 |
| - ); |
38 |
| - } |
| 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 | + ); |
39 | 32 | }
|
| 33 | + } |
40 | 34 |
|
41 |
| - const key = JSON.stringify(args); |
42 |
| - if (cache.has(key)) { |
43 |
| - return cache.get(key); |
44 |
| - } |
| 35 | + const key = JSON.stringify(args); |
| 36 | + if (cache.has(key)) { |
| 37 | + return cache.get(key) as Return; |
| 38 | + } |
45 | 39 |
|
46 |
| - const result = originalMethod.apply(this, args); |
47 |
| - cache.set(key, result); |
| 40 | + const result = target.apply(this, args); |
| 41 | + cache.set(key, result); |
48 | 42 |
|
49 |
| - return result; |
50 |
| - }, |
| 43 | + return result; |
51 | 44 | };
|
52 | 45 | }
|
53 | 46 |
|
|
0 commit comments