我想为属性创建一个装饰,允许我自动添加属性而无需将其写入构造函数。我是Java / Type脚本的新手,所以我希望我没有这么糟糕。我似乎无法做到这一点,这就是我到目前为止所做的......
目标是通过以下方式:
class A {
@uuid
'property': string;
'another': string;
}
function uuid(target: any, key: string): void {
Reflect.defineMetadata('isUuid', true, target, key);
}
我以后可以使用A
的构造函数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
的实例才能获取密钥并获取这些密钥的元数据。
答案 0 :(得分:0)
如果您需要访问每个房产,您将需要装饰每个房产。由于reflect-metadata
API不允许您枚举对象上使用的targetKey
,因此您应该将元数据存储在对象本身上。
首先,定义要为每个属性记录的信息类型。到目前为止,还有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}
// }
这对你有用吗?