Skip to content

Instantly share code, notes, and snippets.

@421p
Last active June 12, 2022 22:21
Show Gist options
  • Save 421p/2a32a5aa7cd1ed4bb55413ca34c1b0c3 to your computer and use it in GitHub Desktop.
Save 421p/2a32a5aa7cd1ed4bb55413ca34c1b0c3 to your computer and use it in GitHub Desktop.
Lazy / Memoize decorator for TypeScript's getter
export function memoize(target: any, prop: string, descriptor: PropertyDescriptor)
{
let original = descriptor.get;
descriptor.get = function (...args: any[])
{
const privateProp = `__memoized_${prop}`;
if (!this.hasOwnProperty(privateProp)) {
Object.defineProperty(this, privateProp, {
configurable: false,
enumerable: false,
writable: false,
value: original.apply(this, args)
});
}
return this[privateProp];
};
}
export class Foo{
@memoize get bar()
{
return 1 + 1; // will be calculated once and then cached
}
}
@rob4226
Copy link

rob4226 commented Jun 12, 2022

Nice, thanks for posting! I also made a decorator to memoize an accessor get but I used a closure to store the memoized value:

export function memoize(_target: any,  _prop: string,  descriptor: PropertyDescriptor): void {
  let original = descriptor.get;
  let cachedValue: any; // Store value in closure scope.

  descriptor.get = function () {
    if (!cachedValue) {
      cachedValue = original.call(this);
      original = undefined; // Drop reference to original function to allow it to be garbage collected.
    }
    return cachedValue;
  };
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment