Readonly Modifier

Actually, I think it is almost possible. After doing a quick glance over the decorator proposal, I see they're providing a new "accessor" property type, that auto-defines a getter and setter on the class, and can be decorated.

So, you could have a decorator such as this:

class MyClass {
  @externallyReadOnly accessor myData = 2
}

And have the decorator desurgar that to this:

class MyClass {
  get myData() {
    return ...
  }
  set myData(newVal) {
    if (!new.self) throw new Error('Can not read this property from outside')
    ... = newVal
  }
}

The ... would be replaced with accessing/setting metadata stuff, that I see decorators support. The decorator would be able to properly default-initialize to the correct value. (In the above example, it would be default-initialized to 2).

The only missing piece is "new.self" that @Jonas_Wilms proposed here in order to enable private constructors. The idea of "new.self" is that it'll simply return true if you're being called from within a class definition, and false otherwise. I don't think this exact idea would be useable here, as the actual getter/setter definitions are created from outside the class, by the decorator, so new.self wouldn't be able to target the class, but perhaps we could find a solution that could work for both use cases.

I'd rather we find a way to empower decorators to support this kind of feature (and perhaps provide built-in convenient decorators if wanted), then add new syntax to achieve this.

Edit: But the get state = #state syntax shorthand looks pretty cool too,. Or, even better, if you could just define getters as arrow functions, so they weren't so verbose, e.g. get state = () => this.#state

1 Like