web-dev-qa-db-fra.com

Obtenir les propriétés de la classe en dactylographié

J'ai le cours suivant:

export class Test {

        private _rowsCount: string;
        public get RowsCount(): string {
            return this._rowsCount;
        };
        public set RowsCount(value: string) {
            this._rowsCount = value;
        };

        private _rowsCount2: string;
        public get RowsCount2(): string {
            return this._rowsCount2;
        };
        public set RowsCount2(value: string) {
            this._rowsCount2 = value;
        };
    }

Je dois parcourir les propriétés d'une classe spécifique, j'ai essayé les solutions suivantes:

Object.keys(this).forEach((key)=> {
    console.log(key);
});

Mais le problème que cette itérer juste au-dessus des champs private, j'ai également essayé le suivant, j'ai eu tous les methods et properties:

    for (var property in this) {
        if (this.hasOwnProperty(property)) {
            console.log(property);                
        }
    }

Quelqu'un a-t-il une solution?

Merci!

13
Ramzy Abourafeh

Si vous ne devez obtenir que les accesseurs/configurateurs, vous devrez faire quelque chose comme:

class Test {
    ...

    public static getGetters(): string[] {
        return Object.keys(this.prototype).filter(name => {
            return typeof Object.getOwnPropertyDescriptor(this.prototype, name)["get"] === "function"
        });
    }

    public static getSetters(): string[] {
        return Object.keys(this.prototype).filter(name => {
            return typeof Object.getOwnPropertyDescriptor(this.prototype, name)["set"] === "function"
        });
    }
}

Test.getGetters(); // ["RowsCount", "RowsCount2"]
Test.getSetters(); // ["RowsCount", "RowsCount2"]

( code dans la cour de récréation )


Vous pouvez placer les méthodes statiques dans une classe de base, puis lorsque vous l'étendez, la sous-classe aura également ces méthodes statiques:

class Base {
    public static getGetters(): string[] {
        return Object.keys(this.prototype).filter(name => {
            return typeof Object.getOwnPropertyDescriptor(this.prototype, name)["get"] === "function"
        });
    }

    public static getSetters(): string[] {
        return Object.keys(this.prototype).filter(name => {
            return typeof Object.getOwnPropertyDescriptor(this.prototype, name)["set"] === "function"
        });
    }
}

class Test extends Base {
   ...
}

Test.getGetters(); // work the same

( code dans la cour de récréation )

Si vous souhaitez que ces méthodes soient des méthodes d'instance, procédez comme suit:

class Base {
    public getGetters(): string[] {
        return Object.keys(this.constructor.prototype).filter(name => {
            return typeof Object.getOwnPropertyDescriptor(this.constructor.prototype, name)["get"] === "function"
        });
    }

    public getSetters(): string[] {
        return Object.keys(this.constructor.prototype).filter(name => {
            return typeof Object.getOwnPropertyDescriptor(this.constructor.prototype, name)["set"] === "function"
        });
    }
}

Le changement est qu'au lieu d'utiliser this.prototype, vous utilisez this.constructor.prototype.
Alors vous simplement:

let a = new Test();
a.getGetters(); // ["RowsCount", "RowsCount2"]

( code dans la cour de récréation )


Modifier

Basé sur un commentaire de @Twois, qui a souligné que cela ne fonctionnerait pas si vous visiez es6, voici une version qui fonctionnera:

class Base {
    public static getGetters(): string[] {
        return Reflect.ownKeys(this.prototype).filter(name => {
            return typeof Reflect.getOwnPropertyDescriptor(this.prototype, name)["get"] === "function";
        }) as string[];
    }

    public static getSetters(): string[] {
        return Reflect.ownKeys(this.prototype).filter(name => {
            return typeof Reflect.getOwnPropertyDescriptor(this.prototype, name)["set"] === "function";
        }) as string[];
    }
}

La principale différence: utiliser Reflect.ownKeys(this.prototype) au lieu de Object.keys(this.prototype).

6
Nitzan Tomer

Ce que vous pouvez faire, c'est pour la classe que vous souhaitez utiliser, étendre la classe ci-dessus et rendre les propriétés publiques pour cette raison

   class TestExposed extend Test {
      public _rowsCount: string;
      public _rowsCount2: string; 
   }

Et dans votre classe de test, protégez le privé:

class Test {
    protected _rowsCount: string;
    public get RowsCount(): string {
        return this._rowsCount;
    };
    public set RowsCount(value: string) {
        this._rowsCount = value;
    };

    protected _rowsCount2: string;
    public get RowsCount2(): string {
        return this._rowsCount2;
    };
    public set RowsCount2(value: string) {
        this._rowsCount2 = value;
    };
}

Ensuite, vous devriez pouvoir parcourir les propriétés d'une classe externe. 

Mais si vous voulez avoir les valeurs; Pourquoi ne pas créer une fonction qui expose les valeurs en les renvoyant dans un tableau ou en les enregistrant sous forme de chaîne;

1
Stef van den Berg