How to add a computed property with a setter in Ember 3.5+?

I have recently upgraded my Ember app from 2.18 to 3.4 and now get this deprecation:

[DEPRECATED] computed property 'xxx' was not set on object 'yyy' via 'defineProperty'

I am defining computed properties onto the prototype of a class at runtime. Currently like this:

prototype[attribute] = computed(...observableProperties, {
    get(key) {
        ...
    },
    set(key, value) {
        ...
    },
}));

The deprecation advises to use defineProperty as a replacement, but if I do this

defineProperty(prototype, attribute, computed(...observableProperties, {
    get(key) {
        ...
    },
    set(key, value) {
        ...
    },
}));

Then the getter works fine but the setter is not added to the property and I get this error

Cannot set property xxx of [object Object] which has only a getter

I took at look into how defineProperty is defined and it only seems to set the getter. (from ember-metal/lib/properties.ts:192)

    Object.defineProperty(obj, keyName, {
      configurable: true,
      enumerable,
      get: DESCRIPTOR_GETTER_FUNCTION(keyName, value),
    });

I tried using Mixin instead of defineProperty but that ultimately executed the same Object.defineProperty.

How can I add a computed property with a setter in Ember 3.x? I can live with the deprecation in Ember 3.4 but in 3.5 the deprecated functionality is removed. Thanks for any advice!

Does anyone have any idea on this? Should I raise an issue on the main repo? Or maybe I need to raise an RFC to have this functionality formally added to defineProperty?

Can you share the full class you’re trying to place a computed property on?

Hey, I setup a quick example to reproduce this issue and define property seems to work just fine with the set property. Example twiddle here.

Can you share a little more of what you’re doing around the define property call?

Are you using Object.defineProperty or Ember.defineProperty? In order to get computed properties to work, you should be using Ember.defineProperty (or import { defineProperty } from '@ember/object'; )

1 Like