在运行时获取对象的类名


271

是否可以在运行时使用TypeScript获取对象的类/类型名称?

class MyClass{}

var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"

3
这里。在运行时,您正在运行JavaScript。
马特·伯兰德

1
但是,如何在TypeScript文件中获取构造函数名称?您不能在TypeScript方法(在.ts文件中)中执行this.constructor.name。
sheldon_cooper 2012年

Answers:


461

简单的答案:

class MyClass {}

const instance = new MyClass();

console.log(instance.constructor.name); // MyClass
console.log(MyClass.name);              // MyClass

但是:请注意,使用缩小代码时,名称可能会有所不同。


14
不幸的是MyClass.name是ES6功能,因此在IE11中不起作用。
贝吉2016年

9
打字稿将对此抛出错误。应该做的let instance: any = this.constructor; console.log(instance.name);
Subash

7
@Subash一种避免强制转换的更简单的方法anyconsole.log(instance.constructor['name']);
Nick Strupat

1
@Subash您也可以创建一个类型声明:interface Function { name: string; }-这将扩展“本地”定义。
John Weisz

1
MyClass.name如果要缩小代码,效果将不佳。因为它将缩小类的名称。
AngryHacker

28

我知道我参加晚会很晚,但是我发现这也行得通。

var constructorString: string = this.constructor.toString();
var className: string = constructorString.match(/\w+/g)[1]; 

或者...

var className: string = this.constructor.toString().match(/\w+/g)[1];

上面的代码将整个构造函数代码作为字符串获取,并应用正则表达式以获取所有“单词”。第一个单词应该是“功能”,第二个单词应该是类的名称。

希望这可以帮助。


4
不好意思 通常,您使用缩小,丑化和其他后期处理系统。因此,在生产服务器上,您的类名将不同。而且您的代码将无法正常工作。我没有找到很好的解决方案来获取类名。最合适的方法是用您的类名定义一个静态变量。
迪马·库里洛

23

我的解决方案是不依赖类名。object.constructor.name在理论上起作用。但是,如果您在Ionic之类的产品中使用TypeScript,那么一旦投入生产,它就会大打折扣,因为Ionic的生产模式会缩减Javascript代码。因此,这些类得到了诸如“ a”和“ e”之类的命名名称。

我最终要做的是,在我的所有对象中都有一个typeName类,构造函数将其分配给该类名。所以:

export class Person {
id: number;
name: string;
typeName: string;

constructor() {
typeName = "Person";
}

是的,这不是真正的要求。但是,在可能会逐渐缩小的东西上使用constructor.name只是让人头疼。


19

看到这个问题

由于TypeScript已编译为JavaScript,因此在运行时将运行JavaScript,因此将应用相同的规则。


14

您首先需要将实例转换为,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"

2
在TypeScript 2.6.2上尝试过,但出现此错误:Property 'name' does not exist on type 'Function'.
orad

(this as {}).constructor.name还是(this as object).constructor.nameany这要好,因为您实际上可以自动完成:-)
Simon_Weaver

5

在Angular2中,这可以帮助获取组件名称:

    getName() {
        let comp:any = this.constructor;
        return comp.name;
    }

comp:any是必需的,因为Type函数最初没有属性名称,因此TypeScript编译将发出错误。


5
但是,如果您缩小/缩小代码,这将不起作用
Admir Sabanovic,2016年

要获取组件的可用“名称”,最好获取tagName为element.nativeElement-在指令上,您可以像这样获取组件的名称@Optional() element: ElementRef<HTMLElement>,然后使用 if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; }
Simon_Weaver

(标签名称不会被缩小)
Simon_Weaver

4

完整的TypeScript代码

public getClassName() {
    var funcNameRegex = /function (.{1,})\(/;
    var results  = (funcNameRegex).exec(this["constructor"].toString());
    return (results && results.length > 1) ? results[1] : "";
}

4
如果您最小化和优化您的打字稿/ JavaScript代码,可能会遇到一些问题。它可能会更改函数名,然后您的类名比较可能是错误的。
Antti,2015年

4
  • 必须添加“ .prototype。 ”才能使用:myClass.prototype.constructor.name
  • 否则使用以下代码: myClass.constructor.name,我遇到TypeScript错误:

error TS2339: Property 'name' does not exist on type 'Function'


0

该解决方案在最小化丑陋之后起作用,但是需要用元数据修饰类。

我们使用代码生成来像这样用元数据修饰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);
}

-2

如果您已经知道需要什么类型(例如,当方法返回联合类型时),则可以使用类型保护。

例如,对于原始类型,您可以使用typeof Guard

if (typeof thing === "number") {
  // Do stuff
}

对于复杂类型,可以使用instanceof guard

if (thing instanceof Array) {
  // Do stuff
}

我猜是因为您的答案与问题无关。问题是要获取类名,而不要有条件地对实例类型执行操作。
丹尼尔·莱森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.