Reputation: 36311
I am making an editor that will look at javascript classes (es6), and display particular information about key properties. I wanted to try and use decorators to accomplish this, so something like this:
class Transform extends Component {
@serializable
public position: Vector3 = Vector3.zero;
}
Then my decorator would looks something like this:
function serializable(...args): any {
let target = args[0];
let key = args[1];
let descriptor = args[2] || {};
descriptor.writable = true;
descriptor.serializable = true;
return descriptor;
}
Then when I am analyzing the class I would do something like this:
components.forEach(comp => {
var info = Object.getOwnPropertyDescriptor(comp, 'position');
if(info.serializable){
// display in editor
}
});
The issue I am having is that it will let me set additional descriptor values, but I can not access them.
What could I do to accomplish this?
Upvotes: 0
Views: 67
Reputation: 164147
I have to admit that it's not very clear from the documentation, because it states that:
NOTE A Property Descriptor is not provided as an argument to a property decorator due to how property decorators are initialized in TypeScript. This is because 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.
But then:
If the property decorator returns a value, it will be used as the Property Descriptor for the member
So my understand was that while the function doesn't get the descriptor to change, it can "change it" by returning a descriptor like you did.
But I guess that this isn't the case as it doesn't work.
However, just below that it gives an example of how to do that using reflect-metadata:
import "reflect-metadata";
const serializableMetadataKey = "serializable";
function serializable(): any {
return Reflect.metadata(serializableMetadataKey, true);
}
function isSerializable(target: any, propertyKey: string) {
return Reflect.getMetadata(serializableMetadataKey, target, propertyKey);
}
class Transform extends Component {
@serializable()
public position: Vector3 = Vector3.zero;
}
components.forEach(comp => {
if (isSerializable(comp, "position")) {
// display in editor
}
});
Upvotes: 1