2017-09-27 70 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