I don't think is possible but it's worth asking. In a generic method or class, I would like to log the name of the generic T type that has been used, I need it as string.
Imagine a method like this:
static getTypeName<T>(): string {
return typeof T; // This is wrong
}
I would expect to be able to use it this way:
let m = getTypeName<Message>(); // Expected string "Message"
let p = getTypeName<Person>(); // Expected string "Person"
The above getTypeName is wrong, it won't even build. typeof would be transpiled in JS and wouldn't produce the desired effect. I tried various things but with no success.
Is there any way to actually do it?
EDIT: Why this is not a duplicate of: this question
The question and the example code shows how to get back an object and not the name of the type specified. Also the method is not generic because if you try to pass in a Type that has constructor parameters it will show the error: "[ts] Argument of type 'typeof MyType' is not assignable to parameter of type 'new () => MyType'." Moreover, if you use the function within a generic method you cannot use T as parameter, this means that everywhere I would need to get the name from the generic Type, I would need to add the ctor to the parameters.
This article opts to use the term type variables, coinciding with the official Typescript documentation. T stands for Type, and is commonly used as the first type variable name when defining generics. But in reality T can be replaced with any valid name.
TypeScript generic type To identify a generic type, you must prefix the function with <Type> where Type is the generic variable. Note: We often use T for generic types. However, it's not limited to any name. Let's redo the above function as a generic typed function.
By passing in the type with the <number> code, you are explicitly letting TypeScript know that you want the generic type parameter T of the identity function to be of type number . This will enforce the number type as the argument and the return value.
An array in TypeScript can contain elements of different data types using a generic array type syntax, as shown below. let values: (string | number)[] = ['Apple', 2, 'Orange', 3, 4, 'Banana']; // or let values: Array = ['Apple', 2, 'Orange', 3, 4, 'Banana'];
Well, Generics in TypeScript is just a construct that helps in typechecking. "T" is in fact "nothing" - it's nothing that can be transpiled into JavaScript. But you need this constructor thing to get your types name. That is why you get that error message. You provided just a type but required is a value (that has that constructor thing) to get your code to work.
Edit:
What you need to do in any case is to provide some JavaScript object. Something like this would work:
class Foo<T> {
test: T;
constructor(value: T) {
this.test = value;
}
getTypeNameOfTest(): string {
return this.test.constructor.name;
}
}
const foo = new Foo<Date>(new Date());
foo.getTypeNameOfTest(); // => "Date"
const baa = new Foo<string>("Howdy");
baa.getTypeNameOfTest(); // => "string"
But here you provide a real JavaScript object instead of just a TypeScript type name. That's why this works.
After searching all the internet, making my own decorator and fiddling with Typescript A LOT, I tripped over this post:
Get an object's class name at runtime
Basically, you can use Message.name
as long as Message
is a class.
Be careful, though, because if class names are minified when doing a production build, this can stop working, so check before using this approach.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With