Ist es möglich, den Klassen- / Typnamen eines Objekts zur Laufzeit mit TypeScript abzurufen?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Ist es möglich, den Klassen- / Typnamen eines Objekts zur Laufzeit mit TypeScript abzurufen?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Antworten:
class MyClass {}
const instance = new MyClass();
console.log(instance.constructor.name); // MyClass
console.log(MyClass.name); // MyClass
Beachten Sie jedoch, dass der Name bei Verwendung von minimiertem Code wahrscheinlich anders sein wird.
let instance: any = this.constructor; console.log(instance.name);
anyistconsole.log(instance.constructor['name']);
interface Function { name: string; }- Dadurch wird die "native" Definition erweitert.
MyClass.namefunktioniert nicht gut, wenn Sie Ihren Code minimieren. Weil dadurch der Name der Klasse minimiert wird.
Ich weiß, dass ich zu spät zur Party komme, aber ich finde, dass das auch funktioniert.
var constructorString: string = this.constructor.toString();
var className: string = constructorString.match(/\w+/g)[1];
Alternative...
var className: string = this.constructor.toString().match(/\w+/g)[1];
Der obige Code ruft den gesamten Konstruktorcode als Zeichenfolge ab und wendet einen regulären Ausdruck an, um alle 'Wörter' zu erhalten. Das erste Wort sollte "Funktion" sein und das zweite Wort sollte der Name der Klasse sein.
Hoffe das hilft.
Meine Lösung bestand darin, mich nicht auf den Klassennamen zu verlassen. object.constructor.name funktioniert theoretisch. Wenn Sie jedoch TypeScript in etwas wie Ionic verwenden, geht es in Flammen auf, sobald Sie zur Produktion gehen, da der Produktionsmodus von Ionic den Javascript-Code minimiert. So erhalten die Klassen benannte Dinge wie "a" und "e".
Am Ende hatte ich in allen meinen Objekten eine typeName-Klasse, der der Konstruktor den Klassennamen zuweist. So:
export class Person {
id: number;
name: string;
typeName: string;
constructor() {
typeName = "Person";
}
Ja, das wurde wirklich nicht gefragt. Die Verwendung des Konstruktornamens für etwas, das möglicherweise später minimiert wird, bittet jedoch nur um Kopfschmerzen.
Siehe diese Frage .
Da TypeScript zu JavaScript kompiliert wird, führen Sie zur Laufzeit JavaScript aus, sodass dieselben Regeln gelten.
Sie müssen die Instanz zuerst umwandeln, anyda Functiondie Typdefinition keine nameEigenschaft hat.
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"
Mit TypeScript 2.4 (und möglicherweise früher) kann der Code noch sauberer sein:
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.nameoder (this as object).constructor.nameist besser als anyweil du dann tatsächlich Autocomplete bekommst :-)
Der vollständige TypeScript-Code
public getClassName() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec(this["constructor"].toString());
return (results && results.length > 1) ? results[1] : "";
}
In Angular2 kann dies helfen, den Komponentennamen zu erhalten:
getName() {
let comp:any = this.constructor;
return comp.name;
}
comp: any wird benötigt, da beim Kompilieren von TypeScript Fehler auftreten, da Function zunächst keinen Eigenschaftsnamen hat.
element.nativeElement- In einer Direktive können Sie den Namen der Komponente wie @Optional() element: ElementRef<HTMLElement>if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; }
Diese Lösung funktioniert nach der Hässlichkeit der Minifizierung, erfordert jedoch das Dekorieren der Klassen mit Metadaten.
Wir verwenden die Codegenerierung, um unsere Entitätsklassen mit folgenden Metadaten zu dekorieren:
@name('Customer')
export class Customer {
public custId: string;
public name: string;
}
Dann konsumieren Sie mit folgendem Helfer:
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);
}
Wenn Sie bereits wissen, welche Typen zu erwarten sind (z. B. wenn eine Methode einen Vereinigungstyp zurückgibt ), können Sie Typschutz verwenden.
Für primitive Typen können Sie beispielsweise einen Schutztyp verwenden :
if (typeof thing === "number") {
// Do stuff
}
Für komplexe Typen können Sie eine Instanz von guard verwenden :
if (thing instanceof Array) {
// Do stuff
}