在TypeScript中运行时获取对象的类名

Ada*_*lls 233 typescript

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

class MyClass{}

var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
Run Code Online (Sandbox Code Playgroud)

Mik*_*zic 405

简单回答:

class MyClass {}

const instance = new MyClass();

console.log(instance.constructor.name); // MyClass
console.log(MyClass.name);              // MyClass
Run Code Online (Sandbox Code Playgroud)

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

  • 不幸的是,MyClass.name是一个ES6功能,因此它在IE11中不起作用. (13认同)
  • 如果您缩小代码,“MyClass.name”将无法正常工作。因为它会缩小类的名称。 (12认同)
  • typescript会在此上抛出错误.应该做`let instance:any = this.constructor; 的console.log(instance.name); ` (9认同)
  • @Subash一种避免转换为`any`的方法是`console.log(instance.constructor ['name']);` (7认同)
  • @Henry据我所知不是。缩小确实会重命名该类。根据您想要实现的目标,在运行时使用构造函数名称可能不是最佳策略。 (2认同)

小智 26

我知道我迟到了,但我发现这也有效.

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

另外...

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

上面的代码将整个构造函数代码作为字符串获取并应用正则表达式来获取所有"单词".第一个单词应该是'function',第二个单词应该是该类的名称.

希望这可以帮助.

  • 对不起,当然.通常,您使用缩小,丑化和其他后处理系统.因此,在生产服务器上,您的类名将不相同.而且你的代码不起作用.我没有找到真正好的解决方案来获得类名.最合适的方法是使用类名定义静态变量. (4认同)

Mat*_*and 19

看到这个问题.

由于TypeScript被编译为JavaScript,因此在运行时您运行的是JavaScript,因此将应用相同的规则.


小智 16

我的解决方案不是依赖类名.object.constructor.name在理论上有效.但是如果你在像Ionic这样的东西上使用TypeScript,那么一旦你进入制作阶段,它就会起火,因为Ionic的制作模式会缩小Javascript代码.因此,类被命名为"a"和"e".

我最终做的是在构造函数为其分配类名的所有对象中都有一个typeName类.所以:

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

constructor() {
typeName = "Person";
}
Run Code Online (Sandbox Code Playgroud)

是的,这不是问的,真的.但是使用constructor.name来解决可能会缩小规模的问题只是让人头疼.

  • 代码缩小后的事件,我相当确定您仍然可以执行``let instance=new Person (); (instance.constructor.name==Person.name)` 两个名称应该缩小为相同的内容。 (6认同)

Wes*_*y92 12

您需要先将实例强​​制转换为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"
Run Code Online (Sandbox Code Playgroud)

更新:

使用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"
Run Code Online (Sandbox Code Playgroud)

  • 尝试使用TypeScript 2.6.2并且我收到此错误:'属性'名称'在类型'Function'上不存在 (2认同)

Flo*_*lox 7

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

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


ttu*_*tes 7

使用在缩小/丑化中幸存下来的装饰器的解决方案

我们使用代码生成来用元数据装饰我们的实体类,如下所示:

@name('Customer')
export class Customer {
  public custId: string;
  public name: string;
}
Run Code Online (Sandbox Code Playgroud)

然后使用以下助手消费:

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);
}
Run Code Online (Sandbox Code Playgroud)

额外信息:

  • 您可能需要安装 reflect-metadata
  • reflect-metadata 是由成员 ot TypeScript 为提议的 ES7 反射 API 编写的 pollyfill
  • 可以在此处跟踪JS 中的装饰器提案


Adm*_*vic 5

在Angular2中,这有助于获取组件名称:

    getName() {
        let comp:any = this.constructor;
        return comp.name;
    }
Run Code Online (Sandbox Code Playgroud)

comp:any是必需的,因为typescript compile会发出错误,因为Function最初没有属性名.

  • 但是,如果您缩小/ uglify您的代码,这将无法正常工作 (5认同)