Typescript:如何仅从类类型获取所有属性装饰器?

xue*_*ang 0 reflection typescript typescript-decorator

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

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

jca*_*alz 5

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

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

然后您仍然可以获取给定属性键的元数据:

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

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

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

甚至获取一个对象,其键是这些属性键,其值是元数据值:

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

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

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

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

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

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

链接到 Stackblitz 中的代码