Czy można uzyskać nazwę klasy / typu obiektu w czasie wykonywania przy użyciu TypeScript?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Czy można uzyskać nazwę klasy / typu obiektu w czasie wykonywania przy użyciu TypeScript?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Odpowiedzi:
class MyClass {}
const instance = new MyClass();
console.log(instance.constructor.name); // MyClass
console.log(MyClass.name); // MyClass
Należy jednak pamiętać, że nazwa będzie prawdopodobnie inna przy użyciu kodu zminimalizowanego.
let instance: any = this.constructor; console.log(instance.name);
anyjestconsole.log(instance.constructor['name']);
interface Function { name: string; }- spowoduje to rozszerzenie definicji „natywnej”.
MyClass.namenie będzie działać dobrze, jeśli minimalizujesz swój kod. Ponieważ zminimalizuje nazwę klasy.
Wiem, że jestem spóźniony na imprezę, ale stwierdzam, że to też działa.
var constructorString: string = this.constructor.toString();
var className: string = constructorString.match(/\w+/g)[1];
Alternatywnie...
var className: string = this.constructor.toString().match(/\w+/g)[1];
Powyższy kod pobiera cały kod konstruktora jako ciąg znaków i stosuje wyrażenie regularne, aby uzyskać wszystkie „słowa”. Pierwszym słowem powinna być „funkcja”, a drugim słowem powinna być nazwa klasy.
Mam nadzieję że to pomoże.
Moim rozwiązaniem nie było poleganie na nazwie klasy. object.constructor.name działa w teorii. Ale jeśli używasz TypeScript w czymś takim, jak Ionic, jak tylko przejdziesz do produkcji, stanie się płomieniem, ponieważ tryb produkcji Ionic minimalizuje kod JavaScript. Tak więc klasy otrzymują nazwy takie jak „a” i „e”.
Skończyło się na tym, że we wszystkich moich obiektach posiadałem klasę typeName, do której konstruktor przypisuje nazwę klasy. Więc:
export class Person {
id: number;
name: string;
typeName: string;
constructor() {
typeName = "Person";
}
Tak, naprawdę nie o to pytano. Ale użycie konstruktora.nazwa na czymś, co może potencjalnie zostać zminimalizowane na drodze, błaga o ból głowy.
Zobacz to pytanie .
Ponieważ TypeScript jest kompilowany do JavaScript, w czasie wykonywania używasz JavaScript, więc obowiązują te same reguły.
Najpierw musisz rzutować instancję, anyponieważ Functiondefinicja typu nie ma namewłaściwości.
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"
W TypeScript 2.4 (i potencjalnie wcześniej) kod może być jeszcze czystszy:
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.namelub (this as object).constructor.namejest lepszy niż anydlatego, że faktycznie dostajesz autouzupełnianie :-)
W Angular2 może to pomóc uzyskać nazwę komponentów:
getName() {
let comp:any = this.constructor;
return comp.name;
}
comp: każdy jest potrzebny, ponieważ kompilacja TypeScript będzie powodować błędy, ponieważ funkcja początkowo nie ma nazwy właściwości.
element.nativeElement- zgodnie z dyrektywą możesz uzyskać nazwę komponentu w ten sposób, @Optional() element: ElementRef<HTMLElement>a następnie użyć if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; }
Pełny kod TypeScript
public getClassName() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec(this["constructor"].toString());
return (results && results.length > 1) ? results[1] : "";
}
To rozwiązanie działa po zmglifikacji minimalizacji, ale wymaga udekorowania klas metadanymi.
Używamy generowania kodu, aby udekorować nasze klasy jednostek za pomocą takich metadanych:
@name('Customer')
export class Customer {
public custId: string;
public name: string;
}
Następnie skonsultuj się z następującym pomocnikiem:
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);
}
Jeśli już wiesz, jakich typów się spodziewać (na przykład, gdy metoda zwraca typ unii ), możesz użyć strażników typów.
Na przykład, dla typów pierwotnych możesz użyć wartownika typeof :
if (typeof thing === "number") {
// Do stuff
}
W przypadku typów złożonych możesz użyć instancji ochrony :
if (thing instanceof Array) {
// Do stuff
}