Est-il possible d'obtenir le nom de classe / type d'un objet lors de l'exécution en utilisant TypeScript?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Est-il possible d'obtenir le nom de classe / type d'un objet lors de l'exécution en utilisant TypeScript?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Réponses:
class MyClass {}
const instance = new MyClass();
console.log(instance.constructor.name); // MyClass
console.log(MyClass.name); // MyClass
Cependant: sachez que le nom sera probablement différent lors de l'utilisation de code minifié.
let instance: any = this.constructor; console.log(instance.name);
anyestconsole.log(instance.constructor['name']);
interface Function { name: string; }- cela étendra la définition "native".
MyClass.namene fonctionnera pas bien si vous réduisez votre code. Parce que cela réduira le nom de la classe.
Je sais que je suis en retard à la fête, mais je trouve que cela fonctionne aussi.
var constructorString: string = this.constructor.toString();
var className: string = constructorString.match(/\w+/g)[1];
Alternativement ...
var className: string = this.constructor.toString().match(/\w+/g)[1];
Le code ci-dessus obtient le code constructeur entier sous forme de chaîne et applique une expression régulière pour obtenir tous les «mots». Le premier mot doit être «fonction» et le deuxième mot doit être le nom de la classe.
J'espère que cela t'aides.
Ma solution était de ne pas compter sur le nom de la classe. object.constructor.name fonctionne en théorie. Mais si vous utilisez TypeScript dans quelque chose comme Ionic, dès que vous allez en production, cela va exploser car le mode de production d'Ionic minimise le code Javascript. Ainsi, les classes reçoivent des noms comme "a" et "e".
Ce que j'ai fini par faire était d'avoir une classe typeName dans tous mes objets auxquels le constructeur attribue le nom de classe. Alors:
export class Person {
id: number;
name: string;
typeName: string;
constructor() {
typeName = "Person";
}
Oui, ce n'était pas vraiment ce qui avait été demandé. Mais utiliser le constructeur.nom sur quelque chose qui pourrait potentiellement être minifié en cours de route est juste un suppliant pour un mal de tête.
Voir cette question .
Étant donné que TypeScript est compilé en JavaScript, au moment de l'exécution, vous exécutez JavaScript, donc les mêmes règles s'appliqueront.
Vous devez d'abord convertir l'instance en anycar Functionla définition de type de n'a pas de namepropriété.
class MyClass {
getName() {
return (<any>this).constructor.name;
// OR return (this as any).constructor.name;
}
}
// From outside the class:
var className = (<any>new MyClass()).constructor.name;
// OR var className = (new MyClass() as any).constructor.name;
console.log(className); // Should output "MyClass"
// From inside the class:
var instance = new MyClass();
console.log(instance.getName()); // Should output "MyClass"
Avec TypeScript 2.4 (et potentiellement plus tôt), le code peut être encore plus propre:
class MyClass {
getName() {
return this.constructor.name;
}
}
// From outside the class:
var className = (new MyClass).constructor.name;
console.log(className); // Should output "MyClass"
// From inside the class:
var instance = new MyClass();
console.log(instance.getName()); // Should output "MyClass"
Property 'name' does not exist on type 'Function'.
(this as {}).constructor.nameou (this as object).constructor.nameest mieux que anyparce que vous obtenez alors la saisie
Dans Angular2, cela peut aider à obtenir le nom des composants:
getName() {
let comp:any = this.constructor;
return comp.name;
}
comp: any est nécessaire car la compilation TypeScript générera des erreurs car Function n'a initialement pas de nom de propriété.
element.nativeElement- Sur une directive, vous pouvez obtenir le nom du composant comme ceci @Optional() element: ElementRef<HTMLElement>, puis utiliser if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; }
Le code TypeScript complet
public getClassName() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec(this["constructor"].toString());
return (results && results.length > 1) ? results[1] : "";
}
Cette solution fonctionne après uglification de minification mais nécessite de décorer les classes avec des métadonnées.
Nous utilisons la génération de code pour décorer nos classes d'entité avec des métadonnées comme ceci:
@name('Customer')
export class Customer {
public custId: string;
public name: string;
}
Consommez ensuite avec l'aide suivante:
export const nameKey = Symbol('name');
/**
* To perserve class name though mangling.
* @example
* @name('Customer')
* class Customer {}
* @param className
*/
export function name(className: string): ClassDecorator {
return (Reflect as any).metadata(nameKey, className);
}
/**
* @example
* const type = Customer;
* getName(type); // 'Customer'
* @param type
*/
export function getName(type: Function): string {
return (Reflect as any).getMetadata(nameKey, type);
}
/**
* @example
* const instance = new Customer();
* getInstanceName(instance); // 'Customer'
* @param instance
*/
export function getInstanceName(instance: Object): string {
return (Reflect as any).getMetadata(nameKey, instance.constructor);
}
Si vous savez déjà à quels types vous attendre (par exemple, lorsqu'une méthode renvoie un type d'union ), vous pouvez utiliser des gardes de type.
Par exemple, pour les types primitifs, vous pouvez utiliser un typeof guard :
if (typeof thing === "number") {
// Do stuff
}
Pour les types complexes, vous pouvez utiliser une instance de guard :
if (thing instanceof Array) {
// Do stuff
}