227

Is it possible to get an object's class/type name at runtime using TypeScript?

class MyClass{}

var instance = new MyClass();
console.log(instance.????); // Should output "MyClass"
               
                     
  • 3                                
    See here. At runtime you are running JavaScript. – Matt Burland Nov 28 '12 at 20:14                                 
  • 1                                
    How do you get the constructor name in TypeScript file though? You can't do this.constructor.name in a TypeScript method (in .ts file). – sheldon_cooper Dec 14 '12 at 15:14                                
  • Cast this to any – Adam Mills Dec 15 '12 at 23:37                                
       

10 Answers 正确答案 


activeoldestvotes                    
       
391

Simple answer :

class MyClass {}

const instance = new MyClass();

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

However: beware that the name will likely be different when using minified code.


  • 12                                    
    Unfortunately MyClass.name is an ES6 feature hence it does not work in IE11. – begie May 9 '16 at 15:30                                    
  • 9                                    
    typescript will throw error on this. should do let instance: any = this.constructor; console.log(instance.name); – Subash Jul 29 '16 at 6:26                                    
  • 7                                    
    @Subash a terser way to avoid casting to any is console.log(instance.constructor['name']); – Nick Strupat Sep 2 '16 at 7:47                                    
  • 1                                    
    @Subash You could also create a type-declaration instead: interface Function { name: string; } -- this will extend the "native" definition. – John Weisz Sep 21 '16 at 12:52                                     
  • How about getting the name of a function? Like the C#'s nameOf ? – gkb Dec 8 '16 at 6:40                                    
       
25

I know I'm late to the party, but I find that this works too.

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

Alternatively...

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

The above code gets the entire constructor code as a string and applies a regex to get all 'words'. The first word should be 'function' and the second word should be the name of the class.

Hope this helps.

improve this answer                            
answered Jun 9 '15 at 6:49                                
                               
user2278642
  • 4                                    
    Sorry, sure. Usually, you use minification, uglyfication and other post processing systems. So on production server your class name will not be the same. And your code will not work. I didn't find really good solution to get class name. The most suitable way is to define a static variable with your class name. – Dima Kurilo Oct 31 '16 at 13:49                                    
       
19

See this question.

Since TypeScript is compiled to JavaScript, at runtime you are running JavaScript, so the same rules will apply.


       
16

My solution was not to rely on the class name. object.constructor.name works in theory. But if you're using TypeScript in something like Ionic, as soon as you go to production it's going to go up in flames because Ionic's production mode minifies the Javascript code. So the classes get named things like "a" and "e."

What I ended up doing was having a typeName class in all my objects that the constructor assigns the class name to. So:

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

constructor() {
typeName = "Person";
}
                       

Yes that wasn't what was asked, really. But using the constructor.name on something that might potentially get minified down the road is just begging for a headache.


       
12

You need to first cast the instance to any because Function's type definition does not have a nameproperty.

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"
                       

Update:

With TypeScript 2.4 (and potentially earlier) the code can be even cleaner:

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                                    
    Tried on TypeScript 2.6.2 and I'm getting this error: Property 'name' does not exist on type 'Function'. – orad Jan 11 '18 at 23:05                                    
  • (this as {}).constructor.name or (this as object).constructor.name is better than anybecause then you actually get autocomplete :-) – Simon_Weaver Jan 16 at 22:31                                    
       
5

In Angular2 this can help to get components name:

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

comp:any is needed because typescript compile will issue errors since Function initially does not have property name.


  • 5                                    
    however this will not work if you minify/uglify your code – Admir Sabanovic Dec 22 '16 at 12:49                                    
  • to get a usable 'name' of a component you're better off getting the tagName of element.nativeElement - On a directive you can get the component's name like this @Optional() element: ElementRef<HTMLElement>and then use if (element != null && element.nativeElement.tagName.startsWith('APP-')) { this.name = element.nativeElement.tagName; } – Simon_Weaver Jan 16 at 22:19                                     
  • (and tag names don't get minified) – Simon_Weaver Jan 16 at 22:21                                    
       
4
  • Had to add ".prototype." to use : myClass.prototype.constructor.name .

  • Otherwise with the following code : myClass.constructor.name, I had the typescript error :

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


       
3

The full TypeScript code

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

  • 4                                    
    You might get some problems if you minimize and optimize your typescript/javascript code. It might change function names and then your class name comparison might be wrong. – Antti Mar 18 '15 at 21:42                                    
       
0

If you already know what types to expect (for example, when a method returns a union type), then you can use type guards.

For example, for primitive types you can use a typeof guard:

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

For complex types you can use an instanceof guard:

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

       
0

Just do

class TestClass {
  getClassName() {
    return this.constructor.name;
  }
   callMe(){
    console.log(this.getClassName());
   }
}
                   

  • Same problem as the accepted answer, which basically is the same: won't work with minified code. – Arjan Jun 27 at 12:25                                    
       

来自  https://stackoverflow.com/questions/13613524/get-an-objects-class-name-at-runtime