Можно ли получить имя класса / типа объекта во время выполнения, используя 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. Таким образом, классы именуются такими вещами, как «а» и «е».
В результате я получил класс typeName во всех моих объектах, которым конструктор назначает имя класса. Так:
export class Person {
id: number;
name: string;
typeName: string;
constructor() {
typeName = "Person";
}
Да, это было не то, что спросили, правда. Но использование constructor.name для чего-то, что потенциально может быть сведено к минимуму, просто умоляет о головной боли.
Смотрите этот вопрос .
Поскольку TypeScript скомпилирован в JavaScript, во время выполнения вы запускаете JavaScript, поэтому будут применяться те же правила.
Сначала необходимо привести экземпляр к, anyтак Functionкак определение типа не имеет 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: any необходим, потому что компиляция 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] : "";
}
myClass.prototype.constructor.name.myClass.constructor.nameменя была ошибка TypeScript: error TS2339: Property 'name' does not exist on type 'Function',
Это решение работает после минимизации, но требует украшения классов метаданными.
Мы используем генерацию кода для украшения наших классов 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 guard :
if (typeof thing === "number") {
// Do stuff
}
Для сложных типов вы можете использовать instanceof guard :
if (thing instanceof Array) {
// Do stuff
}