Typescript属性修饰符可以为类设置元数据吗? [英] can typescript property decorators set metadata for the class?

查看:145
本文介绍了Typescript属性修饰符可以为类设置元数据吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在打字稿中,可以使用属性装饰器来设置类的元数据吗?考虑下面的代码。类装饰器的目标显然与属性装饰器的目标不同。我可以从另一个中获取一个吗?

In typescript, is it possible to use a property decorator to set metadata for the class? Consider the code below. The "target" of the class decorator is apparently not the same as the "target" of the property decorator. Can I derive one from the other?

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' ]

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

How can I get the metadata keys to also show keys from the property decorator?

推荐答案

是的,您可以随意在装饰器中做任何您想做的事,但是如您所知,问题在于传递的目标。

Yes you are free to do whatever you want in your decorator, but as you found out, your issues is with the target you are being passed.

基本上,在属性装饰器中, target 参数可以是两件事之一,具体取决于装饰器用于静态属性或实例属性:

Basically, in a property decorator, the target parameter can be one of two things depending on whether the decorator is used on a static property or an instance property:

在静态属性中, target 属性将是类构造函数。这意味着在静态属性上,目标将与您的类装饰器完全相同。

On a static property, the target property will be the class constructor function. This means that on a static property the target will be exactly the same as it is for your class decorator.

但是,在实例属性上, target 参数将是您创建的类的原型,而不是构造函数。这就是为什么您看到自己所看到的行为。对于实例属性,您的元数据没有像您的类装饰器那样被附加到构造函数

However, on an instance property, the target parameter will be the prototype of the class you created, not the constructor. This is why you are seeing the behavior you are seeing. In the case of an instance property your metadata is not being attached to the constructor as is the case with your class decorator.

尽管如此,还是有希望的,因为给定原型实例的构造函数存储在名为 constructor 的属性中,您可以轻松地访问它。因此,根据您的情况,您可以通过执行以下操作获得所需的行为:

There is still hope though, because you can easily get to the constructor function given a prototype instance as it is stored in a property called constructor. So in your case, you can get the behavior you are looking for by doing this:

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 还是 target.constructor

NOTE: the above change would work for instance properties, but not static properties. If you need to handle both types of properties you would need to add some additional logic to determine whether to use target or target.constructor

这篇关于Typescript属性修饰符可以为类设置元数据吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆