38

My Generic class

 export class BaseService<T> {
 public subUrl;
 constructor(public repo:RepogitoryService) { }
}

How can I store the class name of T on a local variable?

5 Answers5

28

You must understand that Typescript is just a transpiler (compiler to javascript). Some of the syntax sugar (such as generics) are working only in type-checking phase (and also it's helpful for intellisense in your IDE/text-editor).

However assignment to a variable is happening in runtime, in runtime it's just a plain Javascript. There are no types and no generics in runtime.

But here's the easiest way I would do it:

class Some<T> {
    private TName : string;
    constructor(x : T&Function) {
        this.TName = x.name;
    }
}

class Another {

}

const some = new Some<Another>(Another);
durisvk10
  • 549
  • 1
  • 6
  • 11
  • Why TName is private? How to access some.TName? Incomplete answer it seems to me. – hakan Aug 05 '18 at 09:21
  • 16
    @hakan OP asked how to store the generic type name as a local variable, which is exactly what this code does. That variable's visibility is irrelevant to the original question. – Crono Nov 14 '18 at 15:41
  • 2
    This does not seem to work if `Another` had some fields in it. – Marian Simonca Sep 19 '19 at 11:50
24

durisvk10 workaround covers the topic, just want to add that I would rather use
x: new () => T than x: T&Function.

Like this:

...
constructor(x : new () => T) {
    this.TName = x.name;
}    
...
Yaremenko Andrii
  • 759
  • 10
  • 9
  • 3
    Please explain this – Mustafa Magdy Sep 08 '18 at 13:22
  • 5
    You cannot use generics in method body, as it was explained by durisvk10, it's working only in type-checking phase. However you can pass type as argument to your method (constructor in this particular case). And by using this type notation you tells type checker that you expect here type (new () => T) which describes a type with an empty constructor. You can read more about this [here](https://blog.rsuter.com/how-to-instantiate-a-generic-type-in-typescript/) and [here](https://www.typescriptlang.org/docs/handbook/generics.html) – Yaremenko Andrii Sep 10 '18 at 11:08
  • This is quite nice. – avidenic Jul 31 '20 at 08:27
12

You cannot, unfortunately. Typescript is a static type checker and has no support for type reflection at runetime such as java does. This is because its sources are transpiled to javascript.

However, there is hope for such support in the future, with a new typescript feature called "custom transformers". Those transformers are plugins that hook the transpilation process, opening the road to rich features regarding type reflection. A first example of such is ts-transformer-keys.

Jules Sam. Randolph
  • 3,610
  • 2
  • 31
  • 50
4

Cast the object to Object and get constructor name?

function nameOf(object: Object): string {
    return object.constructor.name;
}
lolelo
  • 698
  • 6
  • 18
3

Typescript removes all type information in the emitted Javascript (and thus at runtime), but thanks to Typescript's "transformers" feature, it is now possible to write a transformer to expose this information at runtime. I have done just that, see https://typescript-rtti.org/ - No decorators required, and it is far more comprehensive than emitDecoratorMetadata

William Lahti
  • 1,150
  • 11
  • 11