TypeScript kullanarak çalışma zamanında bir nesnenin sınıf / tür adını almak mümkün müdür?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
TypeScript kullanarak çalışma zamanında bir nesnenin sınıf / tür adını almak mümkün müdür?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Yanıtlar:
class MyClass {}
const instance = new MyClass();
console.log(instance.constructor.name); // MyClass
console.log(MyClass.name); // MyClass
Ancak: küçültülmüş kodu kullanırken adın muhtemelen farklı olacağını unutmayın.
let instance: any = this.constructor; console.log(instance.name);
anyolduğunuconsole.log(instance.constructor['name']);
interface Function { name: string; }- bu, "yerel" tanımı genişletir.
MyClass.namekodunuzu küçültüyorsanız iyi çalışmaz. Çünkü sınıfın adını minimize edecektir.
Partiye geç kaldığımı biliyorum, ama bunun da işe yaradığını görüyorum.
var constructorString: string = this.constructor.toString();
var className: string = constructorString.match(/\w+/g)[1];
Alternatif ...
var className: string = this.constructor.toString().match(/\w+/g)[1];
Yukarıdaki kod, tüm yapıcı kodunu bir dize olarak alır ve tüm 'kelimeleri' almak için bir normal ifade uygular. İlk kelime 'işlev', ikinci kelime sınıfın adı olmalıdır.
Bu yardımcı olur umarım.
Benim çözümüm sınıf ismine güvenmek değildi. object.constructor.name teoride çalışır. Ancak TypeScript'i Ionic gibi bir şeyde kullanıyorsanız, üretime girer girmez alevler içinde yükselir, çünkü Ionic'in üretim modu Javascript kodunu en aza indirir. Böylece sınıflara "a" ve "e" gibi adlar verilir.
Yaptığım şey, yapıcıya sınıf adını atadığı tüm nesnelerimde bir typeName sınıfına sahip olmaktı. Yani:
export class Person {
id: number;
name: string;
typeName: string;
constructor() {
typeName = "Person";
}
Evet, gerçekten sorulan şey bu değildi. Ancak constructor.name dosyasını potansiyel olarak küçültülebilecek bir şeyde kullanmak sadece baş ağrısı için yalvarıyor.
Bu soruya bakın .
TypeScript JavaScript'e derlendiğinden, çalışma zamanında JavaScript çalıştırıyorsunuz, bu nedenle aynı kurallar geçerli olacaktır.
Örneği türüne atamanız gerekir anyçünkü Function's tür tanımının bir nameözelliği yoktur.
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"
TypeScript 2.4 (ve muhtemelen daha önce) ile kod daha da temiz olabilir:
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.nameya (this as object).constructor.nameda daha iyidir anyçünkü o zaman aslında otomatik tamamlama alırsınız :-)
Angular2'de bu bileşen adının alınmasına yardımcı olabilir:
getName() {
let comp:any = this.constructor;
return comp.name;
}
comp: Herhangi biri gereklidir çünkü TypeScript derlemesi İşlev başlangıçta özellik adına sahip olmadığından hatalar verir.
element.nativeElement- Direktifte bileşenin adını bu şekilde alabilir @Optional() element: ElementRef<HTMLElement>ve kullanabilirsiniz if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; }
Tam TypeScript kodu
public getClassName() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec(this["constructor"].toString());
return (results && results.length > 1) ? results[1] : "";
}
Bu çözüm, küçültme uglification sonra çalışır, ancak sınıfları meta veri ile dekore gerektirir.
Entity sınıflarımızı meta verilerle süslemek için kod oluşturma yöntemini kullanırız:
@name('Customer')
export class Customer {
public custId: string;
public name: string;
}
Ardından aşağıdaki yardımcıyla tüketin:
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);
}
Hangi türlerin bekleneceğini zaten biliyorsanız (örneğin, bir yöntem bir birleşim türü döndürdüğünde ), tür korumaları kullanabilirsiniz.
Örneğin, ilkel tipler için bir tip guard kullanabilirsiniz :
if (typeof thing === "number") {
// Do stuff
}
Karmaşık tipler için bir koruma örneği kullanabilirsiniz :
if (thing instanceof Array) {
// Do stuff
}