Yes, you can do whatever you want in your decorator, but as you know, your problems are related to the goal that you pass on.
Basically, in a property decorator, the target
parameter can be one of two things, depending on whether the decorator is used for a static property or an instance property:
In the static property, the target
property will be a class constructor function. This means that with a static property, the target will be exactly the same as for your class decorator.
However, in the instance property, the target
parameter will be the prototype
of the class you created, not the constructor. That is why you see the behavior that you see. In the case of an instance property, your metadata is not bound to a constructor
, as is the case with your class decorator.
However, there is hope, because you can easily get to the constructor function specified by the prototype instance, since it is stored in a property called constructor
. Thus, in your case, you can get the behavior you are looking for by doing the following:
export const MyPropertyDecorator = (options): PropertyDecorator => { return (target, property) => { var classConstructor = target.constructor; console.log('property target: ' , classConstructor); const metadata = Reflect.getMetadata(MY_PROPERTY_DECORATOR_KEY, classConstructor) || {}; metadata[property] = options; Reflect.defineMetadata(MY_PROPERTY_DECORATOR_KEY, metadata, classConstructor); }; };
NOTE: the above change will work for instance properties, but not for static properties. If you need to handle both types of properties, you will need to add additional logic to determine whether to use target
or target.constructor