可以使用typescript属性装饰器为类设置元数据吗?

bki*_*808 9 reflection metadata decorator typescript

在typescript中,是否可以使用属性装饰器为类设置元数据?请考虑以下代码.类装饰器的"目标"显然与属性装饰器的"目标"不同.我可以从另一个中获得一个吗?

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));
Run Code Online (Sandbox Code Playgroud)

注意输出:

property target:  MyClass {}
property target:  MyClass {}
class target:  function MyClass() {
    }
keys:  [ 'MyClassDecoratorKey' ]
Run Code Online (Sandbox Code Playgroud)

如何获取元数据键以显示属性装饰器中的键?

dta*_*enc 8

是的,你可以自由地在你的装饰工作中做任何你想做的事情,但是当你发现时,你的问题就在于你正在通过的目标.

基本上,在属性装饰器中,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);
    };
};
Run Code Online (Sandbox Code Playgroud)

注意:上述更改适用于实例属性,但不适用于静态属性.如果您需要处理这两种类型的属性,则需要添加一些额外的逻辑来确定是否使用targettarget.constructor