I am working on custom class property decorator for my Mobx stores, that would automatically add a setter function to that property, like this:
class Hero() {
@setter
title = "knight";
}
const Ed = new Hero()
console.log(Ed.title) //"knight"
Ed.setTitle("Lord")
console.log(Ed.title) //"Lord"
I am working on legacy code that uses a lot of this decorator, but since it's relying on an outdated version of Mobx, I want to have my own decorator. I have a problem, however, to properly bind function call:
import { action } from 'mobx';
const setterName = name => {
return 'set' + name.charAt(0).toUpperCase() + name.slice(1);
};
export function setter(target, propertyName, desc, customName, customSetter) {
let name = customName || setterName(propertyName);
const setterFunction = function(value) {
if (!!customSetter) {
value =
typeof customSetter === 'function'
? customSetter.call(this, value)
: customSetter;
}
if (this[propertyName] !== value) {
this[propertyName] = value;
}
};
const fnDesc = {
value: action(setterFunction),
};
Object.defineProperty(target, name, fnDesc);
return desc && { ...desc, configurable: true };
}
This properly adds method to the object, but it's not bound and sometimes results in this being some component scope rather than always refer to the Class that decorator is placed in. When doing like this:
const fnDesc = {
value: action(setterFunction.bind(target)),
};
Object.defineProperty(target, name, fnDesc);
the scope is bound to the Class itself, not an actual instance. How can I change it so that it is being run in scope of the instance?