2017-09-27 103 views
0

我想创建一个属性的装饰,这将允许我自动添加属性,而无需将其写入构造函数。我对Java/Type脚本相当陌生,所以希望我没有把这个写得太糟糕。我似乎无法做到这一点,这是我迄今为止...Typescript属性修饰器自动添加到原型

的目标是,用线沿线的东西:

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

为什么你需要非uuid属性? – jcalz

+0

我想要做的是使用装饰器为该属性添加额外的条件。这最终将用作数据库表的模型。 – TheHebrewHammer

回答

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} 
// } 

这是否对你的工作?

+0

有趣的是,这是一个好主意。我通过首先检查'key'是否在Object.getOwnPropertyNames(target)'中,然后使用Object.defineProperty(target,key,...)来添加它,结果(昨晚)但我认为你的方式更有意义。 – TheHebrewHammer