Чи можливо отримати ім’я класу / типу об’єкта під час виконання за допомогою TypeScript?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Чи можливо отримати ім’я класу / типу об’єкта під час виконання за допомогою TypeScript?
class MyClass{}
var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Відповіді:
class MyClass {}
const instance = new MyClass();
console.log(instance.constructor.name); // MyClass
console.log(MyClass.name); // MyClass
Однак: будьте уважні, що ім'я, ймовірно, буде різним при використанні мінімізованого коду.
let instance: any = this.constructor; console.log(instance.name);
anyцеconsole.log(instance.constructor['name']);
interface Function { name: string; }- це розширить "рідне" визначення.
MyClass.nameне буде добре, якщо ви мінімізуєте свій код. Тому що це мінімізує назву класу.
Я знаю, що я спізнююсь на вечірку, але знаходжу, що це теж працює.
var constructorString: string = this.constructor.toString();
var className: string = constructorString.match(/\w+/g)[1];
Як варіант ...
var className: string = this.constructor.toString().match(/\w+/g)[1];
Вищевказаний код отримує весь код конструктора як рядок і застосовує регулярний вираз, щоб отримати всі 'слова'. Перше слово має бути "функція", а друге - назва класу.
Сподіваюсь, це допомагає.
Моє рішення полягало не в тому, щоб покладатися на назву класу. object.constructor.name працює теоретично. Але якщо ви використовуєте TypeScript у чомусь схожому на Ionic, як тільки ви переходите до виробництва, він буде горіти полум'ям, оскільки режим виробництва Ionic мінімізує код Javascript. Тож на заняттях називають такі речі, як "a" та "e".
Що я в кінцевому підсумку робив - це мати клас typeName у всіх моїх об'єктах, яким конструктор присвоює ім'я класу. Так:
export class Person {
id: number;
name: string;
typeName: string;
constructor() {
typeName = "Person";
}
Так, насправді не про це питали. Але використання constructor.name на чомусь, що потенційно може бути зменшене в дорозі, просто благає головного болю.
Дивіться це питання .
Оскільки TypeScript компілюється в JavaScript, під час виконання ви запускаєте JavaScript, тому застосовуватимуться ті самі правила.
Вам потрібно спочатку надати екземпляр anyтому Function, що визначення 'type' не має nameвластивості.
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 (а можливо і раніше) код може бути ще чистішим:
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.nameабо (this as object).constructor.nameкраще, ніж anyтому, що тоді ви фактично отримуєте автозаповнення :-)
У Angular2 це може допомогти отримати ім'я компонентів:
getName() {
let comp:any = this.constructor;
return comp.name;
}
comp: будь- яка потрібна, оскільки компіляція TypeScript видасть помилки, оскільки функція спочатку не має імені властивості.
element.nativeElement- У директиві ви можете отримати ім'я компонента, як це, @Optional() element: ElementRef<HTMLElement>а потім використовувати if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; }
Повний код TypeScript
public getClassName() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec(this["constructor"].toString());
return (results && results.length > 1) ? results[1] : "";
}
Це рішення працює після мінімізації мінімізації, але вимагає прикрасити класи метаданими.
Ми використовуємо генерацію коду для прикраси наших курсів Entity такими метаданими:
@name('Customer')
export class Customer {
public custId: string;
public name: string;
}
Потім споживайте наступного помічника:
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);
}
Якщо ви вже знаєте, яких типів очікувати (наприклад, коли метод повертає тип з'єднання ), тоді ви можете використовувати типи захисту.
Наприклад, для примітивних типів можна використовувати захист typeof :
if (typeof thing === "number") {
// Do stuff
}
Для складних типів ви можете використовувати instanceof guard :
if (thing instanceof Array) {
// Do stuff
}