在打字稿中,是否可以使用属性装饰器来设置类的元数据?考虑下面的代码。类装饰器的“目标”显然与属性装饰器的“目标”不同。我可以从另一个派生出一个吗?
import 'reflect-metadata';
const MY_CLASS_DECORATOR_KEY = 'MyClassDecoratorKey';
const MY_PROPERTY_DECORATOR_KEY = 'MyPropertyDecoratorKey';
export const MyClassDecorator = options => {
return function (target) {
console.log('class target: ' , target);
Reflect.defineMetadata(MY_CLASS_DECORATOR_KEY, options, target);
};
};
export const MyPropertyDecorator = (options): PropertyDecorator => {
return (target, property) => {
console.log('property target: ' , target);
const metadata = Reflect.getMetadata(MY_PROPERTY_DECORATOR_KEY, target) || {};
metadata[property] = options;
Reflect.defineMetadata(MY_PROPERTY_DECORATOR_KEY, metadata, target);
};
};
@MyClassDecorator('my class decorator value')
class MyClass {
@MyPropertyDecorator('first my property decorator value')
myFirstProperty: any;
@MyPropertyDecorator('second my property decorator value')
mySecondProperty: any;
}
console.log('keys: ', Reflect.getMetadataKeys(MyClass));
注意输出:
property target: MyClass {}
property target: MyClass {}
class target: function MyClass() {
}
keys: [ 'MyClassDecoratorKey' ]
如何获取元数据键以同时显示属性装饰器中的键?
是的,您可以在装饰器中自由地做任何您想做的事情,但正如您发现的那样,您的问题在于您正在传递的目标。
基本上,在属性装饰器中,target
参数可以是以下两种情况之一,具体取决于装饰器是用于静态属性还是实例属性:
对于静态属性,target
财产将是类构造函数。这意味着静态属性的目标将与类装饰器的目标完全相同。
但是,在实例属性上,target
参数将是prototype
您创建的类的,而不是构造函数的。这就是为什么您会看到您所看到的行为。对于实例属性,您的元数据不会附加到constructor
就像你的类装饰器的情况一样。
不过,仍然有希望,因为给定原型实例,您可以轻松访问构造函数,因为它存储在名为的属性中constructor
。因此,就您的情况而言,您可以通过执行以下操作来获得您正在寻找的行为:
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);
};
};
注意:上述更改适用于实例属性,但不适用于静态属性。如果您需要处理这两种类型的属性,则需要添加一些额外的逻辑来确定是否使用target
or target.constructor
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)