【问题标题】:Typescript: How to get all property decorators from only the class type?Typescript:如何仅从类类型中获取所有属性装饰器?
【发布时间】:2020-04-20 00:45:20
【问题描述】:
const metadataKey = "metadataKey";
class User
{
    @Reflect.metadata(metadataKey, 1)
    name: string;
    @Reflect.metadata(metadataKey, 2)
    age: number;
}

getPropertyDecorators(User); // I hope it can return [1, 2]

我希望函数 getPropertyDecorators 不需要创建 User 的实例。

【问题讨论】:

    标签: typescript reflection typescript-decorator


    【解决方案1】:

    反射元数据中没有内置功能可以执行此操作。您可以自己构建类似的东西,方法是使用反射元数据创建自己的属性装饰器,将属性键列表存储在类的原型上并稍后使用。例如:

    function myPropertyDecorator(
      metadataKey: string,
      metadataValue: any
    ): PropertyDecorator {
      return function(ctorPrototype: any, propertyKey: string): void {
        // original functionality
        Reflect.defineMetadata(
          "data:" + metadataKey,
          metadataValue,
          ctorPrototype,
          propertyKey
        );
    
        // new functionality
        let propertyKeys =
          Reflect.getOwnMetadata("keys:" + metadataKey, ctorPrototype) ||
          (Reflect.getMetadata("keys:" + metadataKey, ctorPrototype) || []).slice(
            0
          );
        Reflect.defineMetadata("keys:" + metadataKey, propertyKeys, ctorPrototype);
    
        // record new property key
        propertyKeys.push(propertyKey);
      };
    }
    

    然后你仍然可以在给定属性键的情况下获取元数据:

    function getMyPropertyDecorator(
      ctor: { prototype: any },
      metadataKey: string,
      propertyKey: string
    ) {
      return Reflect.getMetadata(
        "data:" + metadataKey,
        ctor.prototype,
        propertyKey
      );
    }
    

    以及枚举您为其存储元数据的所有属性键:

    function getMyPropertyDecoratorPropertyKeys(
      ctor: { prototype: any },
      metadataKey: string
    ) {
      return (Reflect.getMetadata("keys:" + metadataKey, ctor.prototype) ||
        []) as string[];
    }
    

    甚至得到一个对象,其键是那些属性键,其值是元数据值:

    function getMyPropertyDecorators(
      ctor: { prototype: any },
      metadataKey: string
    ) {
      const ret: Record<string, any> = {};
      for (let propertyKey of getMyPropertyDecoratorPropertyKeys(
        ctor,
        metadataKey
      )) {
        ret[propertyKey] = getMyPropertyDecorator(ctor, metadataKey, propertyKey);
      }
      return ret;
    }
    

    这最后一个足以让你做你想做的事:

    const metadataKey = "metadataKey";
    class User {
      @myPropertyDecorator(metadataKey, 1)
      name: string = "1";
      @myPropertyDecorator(metadataKey, 2)
      age: number = 3;
    }
    
    console.log(getMyPropertyDecorators(User, metadataKey)); // {name: 1, age: 2}
    

    如果您想要一个专用函数将值提取到数组中(虽然我不知道您将如何确保排序):

    function getMyPropertyDecoratorValues(
      ctor: { prototype: any },
      metadataKey: string
    ) {
      const myPropertyDecorators = getMyPropertyDecorators(ctor, metadataKey);
      return Object.keys(myPropertyDecorators).map(
        propertyKey => myPropertyDecorators[propertyKey]
      );
    }
    
    
    console.log(getMyPropertyDecoratorValues(User, metadataKey)); // [1, 2]
    

    好的,希望对您有所帮助。祝你好运!

    Link to code in Stackblitz

    【讨论】:

      猜你喜欢
      • 2020-06-20
      • 2015-10-23
      • 2020-06-29
      • 2016-11-13
      • 1970-01-01
      • 2021-05-17
      • 2019-08-21
      • 2019-08-19
      • 2011-12-02
      相关资源
      最近更新 更多