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' ]
メタデータキーを取得して、プロパティデコレータからのキーも表示するにはどうすればよいですか?
はい、デコレータで好きなことを自由に行うことができますが、あなたが知っているように、あなたの問題はあなたが通過しているターゲットにあります。
基本的に、プロパティデコレータでは、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
のどちらを使用するかを決定するロジックを追加する必要があります。