0

我想为属性创建一个装饰,允许我自动添加属性而无需将其写入构造函数。我对 Java/Type 脚本还很陌生,所以希望我没有把这个杀得太糟糕。我似乎无法做到这一点,这是我目前所拥有的......

目标是通过以下方式:

class A {
  @uuid
  'property': string;
  'another': string;
}

function uuid(target: any, key: string): void {
  Reflect.defineMetadata('isUuid', true, target, key);
}

我以后可以使用A's 构造函数new () => Object来获取所有属性的列表以及它们是否是 UUID。我认为这看起来像:

Object.keys(A).forEach(key => {
  console.log(`[${key}].isUuid? ${Reflect.getMetadata('isUuid', A, key) === true}`);
});

这有望产生类似的东西:

[property].isUuid? true
[another].isUuid? false

作为说明,如果我将课程更改A为:

class A {
  constructor() {
    this.property = undefined;
    this.another = undefined;
  }
  @uuid
  'property': string;
  'another': string;
}

我可以让它工作,但我必须创建一个实例A才能获取密钥并获取它们的元数据。

4

1 回答 1

0

如果您需要访问每个属性,则需要装饰每个属性。由于reflect-metadataAPI 不允许您枚举targetKey对象上使用的 s,因此您应该将元数据存储在对象本身上。

首先,定义您要为每个属性记录的信息类型。到目前为止,有isUuid

interface DbPropInfo {
  isUuid: boolean; 
  // other stuff
}

它有助于为每条信息设置一个默认值,因此装饰器注释可以简洁:

const defaultDbPropInfo: DbPropInfo = {
  isUuid: false 
}

我们希望将元数据存储为一个对象,其键与类的属性键相同,其值是DbPropInfo我们为这些属性设置的值。这是该对象的类型:

interface DbProps {
  [k: string]: DbPropInfo;
}

现在对于装饰器:

const dbPropsKey = 'dbProps';

function dbProp(info?: Partial<DbPropInfo>) {
  return function(target: any, key: string): void {
    if (!Reflect.hasMetadata(dbPropsKey, target)) {
      Reflect.defineMetadata(dbPropsKey, {}, target);
    }
    const dbProps: DbProps = Reflect.getMetadata(dbPropsKey, target);
    dbProps[key] = Object.assign({}, defaultDbPropInfo, info);
  }
}

并获取修饰数据:

function getDbProps(ctor: { prototype: any }): DbProps | undefined {
  return Reflect.getMetadata(dbPropsKey, ctor.prototype);
}

最后我们可以在你的课堂上试试:

class A {
  @dbProp({ isUuid: true }) property: string;
  @dbProp() another: string;
}

让我们看看它是否有效:

console.log(JSON.stringify(getDbProps(A)));
// { 
//   "property": {"isUuid": true},
//   "another": {"isUuid": false}
// }

那对你有用吗?

于 2017-09-28T01:23:32.790 回答