tc39 / proposal-decorators-previous

Decorators for ECMAScript
183 stars 16 forks source link

Use case: property observation #1

Closed justinfagnani closed 6 years ago

justinfagnani commented 8 years ago

@littledan asked me for some use cases, so here's my current top use case:

Decorators that replace a class field with a getter/setter pair and auxiliary storage are a great way to implement pre-property change observation. The decorator I use in TypeScript is similar to this:

function observable(clazz, name, descriptor) {
  let getter = descriptor && descriptor.get;
  let setter = descriptor && descriptor.set;
  let storageProp = getter ? name : Symbol(`__prop_${name}`);

  return {
    configurable: true,
    enumerable: true,
    isProperty: true,
    get: getter || (function() { return this[storageProp]; }),
    set(value) {
      let oldValue = this[name];
      if (oldValue !== value) {
        if (setter) {
          setter.call(this, value);
        } else {
          this[storageProp] = value;
        }
        this.dispatchEvent(new CustomEvent(`${name}-changed`, {
          detail: { value, oldValue },
        }));
      }
    },
  };
}

This decorator demonstrates wrapping an existing member, and adding a new private-ish one to the class.

littledan commented 6 years ago

I'm doing a scrub of these bugs. Happy to say that this is still supported in the current version! You can actually use a private field for the underlying storage, so it doesn't pollute the object and all writes are really intercepted.