Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

How would decorators work with fields and get/set? #58

Closed
justinbmeyer opened this issue Feb 2, 2017 · 5 comments
Closed

How would decorators work with fields and get/set? #58

justinbmeyer opened this issue Feb 2, 2017 · 5 comments

Comments

@justinbmeyer
Copy link

justinbmeyer commented Feb 2, 2017

This might be outside the current concerns of this proposal, but I'm wondering how decorators will work alongside fields and get/set.

CanJS has a library can-define we use to add rich behavior to a constructor function and its prototype like this:

var Person = function(){ };
define(Person.prototype,{
  name: {
    value: "Beyonce Knowles",
    set: function(value){
      return value.toUpperCase();
    },
    get: function(value){
      return value.toLowerCase();
    }
  },
  age: {type: "number", age: "35"}
});

var p = new Person();
p.name //-> "beyonce knowles"
p.age //-> 35  (notice it was converted to a number)

value is the initial value of the property. Users expected values to go through the setter, example issue: canjs/can-define#87. I'm trying to figure out how I could migrate this sort of rich behavior to class with decorators, fields, and get/set.

Ideally, something like:

class Person {
  @prop
  name= "Beyonce Knowles";
  set name(newVal){
    return value.toUpperCase();
  },
  get name(newVal){
    return value.toLowerCase();
  }
  @type("number")
  age="35"
}

Would @type get called like:

type( Person.prototype, "age", {value: "35"} )

And be able to provide a get / set definition? Would it get called during the class definition or the construction of the instance?

I doubt it will work this way, but I'd really like @prop to be able to be called with the initial field value:

prop( 
  Person.prototype, 
  "age", 
  {value: "Beyonce Knowles", get: getter, set: setter} )

So I could rewrite the getter/setters to use it if set hasn't been called as follows:

prop = function(prototype, name, definition){
  // create the internal store of data ...
  Object.defineProperty(prototype, "_data", {
    get: function(){
      return this._data = {};
    }
  })
  Object.defineProperty(prototype, name, {
    get: function(){
      // get calls the provided `getter` with the internal data
      return definition.get.call(this, this._data.hasOwnProperty(name) ? this._data[name] :  definition.value );
    },
    set: function(value){
      // set the internal data with the result of the provided `setter`
      this._data[name] = definition.set.call(this, value);
    }
  })
}

Thanks for any clarity you can provide!

@bakkot
Copy link
Contributor

bakkot commented Feb 2, 2017

You might ask over at the decorators proposal, since it looks like your question is more about decorators. (Remember, decorators aren't yet any more part of the language than public fields are, and are no more settled in their behavior!)

@bakkot
Copy link
Contributor

bakkot commented Feb 2, 2017

That said, re:

Users expected values to go through the setter

You might be able to make that happen with a decorator, but without one that comes down to #42. Personally I feel very strongly that public fields should be for defining fields, and if you want to trigger setters and other effects the constructor is the correct place to do it.

@bakkot
Copy link
Contributor

bakkot commented Feb 2, 2017

(Sorry, I didn't mean to imply this issue ought to be closed! Someone else might have more information. Just, people working on the decorators proposal might too :) )

@justinbmeyer
Copy link
Author

No problem. You'd expect the decorators proposal to consider how it would work with this proposal?

@bakkot
Copy link
Contributor

bakkot commented Feb 2, 2017

I know that its champions are considering how it works with this proposal, yes. Both are concerned about working with the other, but most of the machinery you're concerned about would be handled by the decorators proposal.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants