380

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

class MyClass{}

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

10 回答 10

620

简单的回答:

class MyClass {}

const instance = new MyClass();

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

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

于 2016-04-15T09:21:18.610 回答
35

我的解决方案是不依赖类名。object.constructor.name 理论上有效。但是如果你在 Ionic 之类的东西中使用 TypeScript,一旦你投入生产,它就会火上浇油,因为 Ionic 的生产模式会缩小 Javascript 代码。所以类被命名为“a”和“e”。

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

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

constructor() {
typeName = "Person";
}

是的,这不是被问到的,真的。但是在可能会被缩小的东西上使用constructor.name只是在乞求头痛。

于 2017-04-24T21:12:36.843 回答
30

我知道我参加聚会迟到了,但我发现这也行得通。

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

或者...

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

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

希望这可以帮助。

于 2015-06-09T06:49:40.973 回答
20

看到这个问题

由于 TypeScript 被编译为 JavaScript,因此在运行时您正在运行 JavaScript,因此将适用相同的规则。

于 2012-11-28T21:47:47.597 回答
17

您需要先将实例转换为,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"
于 2016-07-30T00:20:32.047 回答
10

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

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

@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);
}

额外信息:

于 2020-06-19T13:43:57.737 回答
5

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

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

comp:any是必需的,因为 TypeScript 编译器会发出错误,因为 Function 最初没有属性名称。

于 2016-06-17T22:07:05.257 回答
5
  • 必须添加“ .prototype. ”才能使用:myClass.prototype.constructor.name.
  • 否则使用以下代码: myClass.constructor.name,我遇到了 TypeScript 错误:

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

于 2017-05-29T10:01:48.500 回答
3

完整的 TypeScript 代码

public getClassName() {
    var funcNameRegex = /function (.{1,})\(/;
    var results  = (funcNameRegex).exec(this["constructor"].toString());
    return (results && results.length > 1) ? results[1] : "";
}
于 2013-06-11T13:24:31.503 回答
-3

如果您已经知道预期的类型(例如,当方法返回联合类型时),那么您可以使用类型保护。

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

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

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

if (thing instanceof Array) {
  // Do stuff
}
于 2017-08-14T18:49:58.653 回答