web-dev-qa-db-ja.com

クラスのプロパティを取得する

TypeScriptでクラスのプロパティ名を取得する方法はありますか?

この例では、クラスAまたは任意のクラスを '記述'し、そのプロパティの配列(おそらくpublicのみ?)を取得したいのですが、可能ですか?または、最初にオブジェクトをインスタンス化する必要がありますか?

class A {
    private a1;
    private a2;
    /** Getters and Setters */

}

class Describer<E> {
    toBeDescribed:E ;
    describe(): Array<string> {
        /**
         * Do something with 'toBeDescribed'                          
         */
        return ['a1', 'a2']; //<- Example
    }
}

let describer = new Describer<A>();
let x= describer.describe();
/** x should be ['a1', 'a2'] */ 
36
mboullouz

このTypeScriptコード

class A {
    private a1;
    public a2;
}

このJavaScriptコードにコンパイルします

class A {
}

これは、JavaScriptのプロパティが何らかの値を取得した後にのみ存在し始めるためです。プロパティに値を割り当てる必要があります。

class A {
    private a1 = "";
    public a2 = "";
}

にコンパイルされます

class A {
    constructor() {
        this.a1 = "";
        this.a2 = "";
    }
}

それでも、単なるクラスからプロパティを取得することはできません(プロトタイプからメソッドのみを取得できます)。インスタンスを作成する必要があります。次に、Object.getOwnPropertyNames()を呼び出してプロパティを取得します。

let a = new A();
let array = return Object.getOwnPropertyNames(a);

array[0] === "a1";
array[1] === "a2";

あなたの例に適用

class Describer {
    static describe(instance): Array<string> {
        return Object.getOwnPropertyNames(instance);
    }
}

let a = new A();
let x = Describer.describe(a);
29
Erik Cupal

一部の答えは部分的に間違っており、その中の一部の事実も部分的に間違っています。

あなたの質問に答えてください:はい!あなたはできる。

TypeScriptで

class A {
    private a1;
    private a2;


}

Javascriptで次の code を生成します。

var A = /** @class */ (function () {
    function A() {
    }
    return A;
}());

@Erik_Cupalが言ったように、あなたはただすることができます:

let a = new A();
let array = return Object.getOwnPropertyNames(a);

しかし、これは不完全です。クラスにカスタムコンストラクターがある場合はどうなりますか? TypeScriptはコンパイルされないため、トリックを行う必要があります。次のものとして割り当てる必要があります。

let className:any = A;
let a = new className();// the members will have value undefined

一般的な解決策は次のとおりです。

class A {
    private a1;
    private a2;
    constructor(a1:number, a2:string){
        this.a1 = a1;
        this.a2 = a2;
    }
}

class Describer{

   describeClass( typeOfClass:any){
       let a = new typeOfClass();
       let array = Object.getOwnPropertyNames(a);
       return array;//you can apply any filter here
   }
}

理解を深めるため、thisはコンテキストに応じて参照します。

14
titusfx

ただの楽しみのために

class A {
    private a1 = void 0;
    private a2 = void 0;
}

class B extends A {
    private a3 = void 0;
    private a4 = void 0;
}

class C extends B {
    private a5 = void 0;
    private a6 = void 0;
}

class Describer {
    private static FRegEx = new RegExp(/(?:this\.)(.+?(?= ))/g); 
    static describe(val: Function, parent = false): string[] {
        var result = [];
        if (parent) {
            var proto = Object.getPrototypeOf(val.prototype);
            if (proto) {
                result = result.concat(this.describe(proto.constructor, parent));
            } 
        }
        result = result.concat(val.toString().match(this.FRegEx) || []);
        return result;
    }
}

console.log(Describer.describe(A)); // ["this.a1", "this.a2"]
console.log(Describer.describe(B)); // ["this.a3", "this.a4"]
console.log(Describer.describe(C, true)); // ["this.a1", ..., "this.a6"]

更新:カスタムコンストラクターを使用している場合、この機能は破損します。

8
madreason

別の解決策は、オブジェクトキーを次のように反復するだけです注:インスタンス化されたオブジェクトを既存のプロパティで使用する必要があります

printTypeNames<T>(obj: T) {
    const objectKeys = Object.keys(obj) as Array<keyof T>;
    for (let key of objectKeys)
    {
       console.Log('key:' + key);
    }
}
7
johnny 5