web-dev-qa-db-fra.com

Obtenir les propriétés d'une classe

Existe-t-il un moyen d'obtenir les noms de propriétés de la classe dans TypeScript?

Dans l'exemple, je voudrais "décrire" la classe A ou n'importe quelle classe et obtenir un tableau de ses propriétés (peut-être que public celles?), Est-ce possible? Ou devrais-je instancier l'objet en premier?

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

Ce code de typeScript

class A {
    private a1;
    public a2;
}

compile à ce code JavaScript

class A {
}

En effet, les propriétés dans JavaScript ne commencent à être existantes qu'après avoir acquis une certaine valeur. Vous devez attribuer une valeur aux propriétés.

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

il se compile pour

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

Néanmoins, vous ne pouvez pas obtenir les propriétés à partir d'une simple classe (vous pouvez uniquement obtenir des méthodes à partir d'un prototype). Vous devez créer une instance. Ensuite, vous obtenez les propriétés en appelant Object.getOwnPropertyNames().

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

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

Appliqué à votre exemple

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

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

Certaines réponses sont partiellement fausses et certains faits sont également fausses.

Répondez à votre question: oui! Vous pouvez.

Dans TypeScript

class A {
    private a1;
    private a2;


}

Génère le texte suivant code en Javascript:

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

comme @Erik_Cupal l'a dit, vous pouvez simplement faire:

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

Mais c'est incomplet . Que se passe-t-il si votre classe a un constructeur personnalisé? Vous devez faire une astuce avec TypeScript car il ne compilera pas. Vous devez assigner en tant que:

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

Une solution générale sera:

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

Pour une meilleure compréhension , ceci référencera en fonction du contexte.

14
titusfx

Juste pour le fun

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"]

Mise à jour: Si vous utilisez des constructeurs personnalisés, cette fonctionnalité sera brisée.

8
madreason

Une autre solution, vous pouvez simplement parcourir les clés d’objet comme suit, Remarque: vous devez utiliser un objet instancié avec des propriétés existantes:

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