Reputation: 17429
How does one implement a TypeScript property descriptor that replaces the accessors, while maintaining composability?
Upvotes: 2
Views: 1850
Reputation: 17429
The TypeScript handbook Decorators chapter seems to imply that it cannot be done, or at least that it is a bad idea. It says...
...there is currently no mechanism to describe an instance property when defining members of a prototype, and no way to observe or modify the initializer for a property. As such, a property decorator can only be used to observe that a property of a specific name has been declared for a class.
However, I found the Object.getOwnPropertyDescriptor(target, key)
which seems to provide what is needed.
Here is an example:
function decorator(name: string) {
return function (target: any, key: string) {
try {
console.log(`${name}...`);
let localValue = undefined;
let prev = Object.getOwnPropertyDescriptor(target, key);
let setter = function (newVal) {
try {
console.log(`${name} setter(${newVal}) called...`);
if (prev) prev.set(newVal);
localValue = newVal;
} finally {
console.log(`...${name} setter called`);
}
};
let getter = function () {
try {
console.log(`${name} getter(${localValue}) called...`);
if (prev) prev.get();
return localValue;
} finally {
console.log(`...${name} getter called`);
}
};
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: prev == null ? true : prev.enumerable,
configurable: prev == null ? true : prev.configurable
});
} finally {
console.log(`...${name}`);
}
}
}
class MyClass {
@decorator("decorator1")
@decorator("decorator2")
myProperty: string;
}
var mc = new MyClass();
mc.myProperty = "asdf";
console.log(mc.myProperty);
The output is:
decorator2...
...decorator2
decorator1...
...decorator1
decorator1 setter(asdf) called...
decorator2 setter(asdf) called...
...decorator2 setter called
...decorator1 setter called
decorator1 getter(asdf) called...
decorator2 getter(asdf) called...
...decorator2 getter called
...decorator1 getter called
asdf
I am not at all sure this is the right way to do this. I would love to receive comments.
Upvotes: 2