2017-02-16 7 views
5

typecriptでは、プロパティデコレータを使用してクラスのメタデータを設定できますか?以下のコードを考えてみましょう。クラスデコレータの「ターゲット」は、明らかにプロパティデコレータの「ターゲット」と同じではありません。他のものから1つを派生させることはできますか?プロパティデコレータは、そのクラスのメタデータをtypescriptできますか?

import 'reflect-metadata'; 


const MY_CLASS_DECORATOR_KEY = 'MyClassDecoratorKey'; 
const MY_PROPERTY_DECORATOR_KEY = 'MyPropertyDecoratorKey'; 

export const MyClassDecorator = options => { 
    return function (target) { 
     console.log('class target: ' , target); 
     Reflect.defineMetadata(MY_CLASS_DECORATOR_KEY, options, target); 
    }; 
}; 

export const MyPropertyDecorator = (options): PropertyDecorator => { 
    return (target, property) => { 
     console.log('property target: ' , target); 
     const metadata = Reflect.getMetadata(MY_PROPERTY_DECORATOR_KEY, target) || {}; 
     metadata[property] = options; 
     Reflect.defineMetadata(MY_PROPERTY_DECORATOR_KEY, metadata, target); 
    }; 
}; 

@MyClassDecorator('my class decorator value') 
class MyClass { 
    @MyPropertyDecorator('first my property decorator value') 
    myFirstProperty: any; 

    @MyPropertyDecorator('second my property decorator value') 
    mySecondProperty: any; 
} 

console.log('keys: ', Reflect.getMetadataKeys(MyClass)); 

注出力:

property target: MyClass {} 
property target: MyClass {} 
class target: function MyClass() { 
    } 
keys: [ 'MyClassDecoratorKey' ] 

はどのようにしても、プロパティデコレータから鍵を表示するには、メタデータのキーを取得することができますか?

答えて

3

はい、あなたはあなたのデコレータで何でも自由に行えますが、あなたが知ったとおり、あなたの問題はあなたが渡されているターゲットにあります。

基本的に、プロパティのデコレータで、targetパラメータは、デコレータは、静的プロパティまたはインスタンスのプロパティに使用されるかどうかに応じて、2つのものの一つであることができる。

静的プロパティで、target性があろうクラスコンストラクタ関数。つまり、静的プロパティでは、ターゲットはクラスデコレータとまったく同じになります。

ただし、インスタンスプロパティの場合、targetパラメータは、作成したクラスのprototypeであり、コンストラクタではありません。これはあなたが見ている行動を見ている理由です。インスタンスプロパティの場合、クラスデコレータの場合のように、メタデータはconstructorにアタッチされていません。

constructorというプロパティに格納されているように、プロトタイプインスタンスが与えられればコンストラクタ関数に簡単にアクセスできるので、まだ希望はあります。だからあなたの場合には、あなたがこれを行うことにより、あなたが探している動作を取得することができます:

export const MyPropertyDecorator = (options): PropertyDecorator => { 
    return (target, property) => { 
     var classConstructor = target.constructor; 
     console.log('property target: ' , classConstructor); 
     const metadata = Reflect.getMetadata(MY_PROPERTY_DECORATOR_KEY, classConstructor) || {}; 
     metadata[property] = options; 
     Reflect.defineMetadata(MY_PROPERTY_DECORATOR_KEY, metadata, classConstructor); 
    }; 
}; 

注:上記の変更をインスタンスのプロパティではなく、静的な性質のために働くだろう。両方のタイプのプロパティを処理する必要がある場合は、使用するかどうかを判断するロジックを追加する必要があります。targetまたはtarget.constructor

+0

素晴らしいです。あなたの答えはまさに私が必要としていたものです。本当にありがとう!しかし、私は他の方向に進み、メタデータをコンストラクタではなくプロトタイプに配置したいとします。私は他の方向に行くことができますか? – bkinsey808

+0

もちろん、target.prototypeを実行してください – dtabuenc

関連する問題