tc39/proposal-decorators

Reactive/observable field without "accessor"?

xaviergonz opened this issue · 4 comments

I was thinking how to make an "observable" field without using accessor, and the following came to my mind

function observable(value, context) {
  return function(initialValue) {
    let v = initialValue
    Object.defineProperty(this, context.name, {
      configurable: true,
      get() { return v },
      set(x) { v = x }
    })

    return v
  }
}

but, at least in the independent playground, that's not allowed because after the init function is called the engine will call define property on its own to actually "define" the property

is there a way to make that pattern work without having to add "accessor" all over the place?

Nope. accessor is what fixes class fields to make them work with inheritance and/or be meta-programmable at all.

It's unfortunate that accessor semantics aren't the default, but here we are.

Ah well, better than nothing I guess.

I can think of another way to avoid accessors though and it is to make the field decorators add the field name to an instance private list and then have a class decorator that will return an extended class which will, on its constructor, read this list and do a defineProperty over each registered field, but then you have to add that extra class decorator...

Is the non-accessor case more common? I fear this is class method binding all over again, where defaulting to unbound functions in classes makes absolutely 0 sense. 🙃

@NullVoxPopuli it is common enough, especially with metadata, that it could cause severe performance impacts in apps which do not need them. It tends to be a highly bifurcated space - either your ecosystem only uses accessor on fields, or never uses it.

The failure case here is also much less severe than method binding. When users forget that methods are not bound by default, they get confusing behavior and error messages which are indirect (e.g. otherMethod is not a function). When users forget to add accessor to a decorated field, the decorator can easily throw a descriptive error message which reminds the user that they need to add accessor (or vice-versa). Editors can also add autocomplete for typing accessor, so it should be much better overall.

A good comparison here is the C# ecosystem, where annotated properties need to add get and set if they want to intercept access (just like here). It works pretty well overall and tooling helps a lot in general.

I'm going to close this issue and this is something we have debated for a long time and made a decision on, for reasons that have been addressed previously.