Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript generic type T toString

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.

like image 564
Norcino Avatar asked Nov 14 '17 16:11

Norcino


People also ask

What is type T in TypeScript?

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.

How do I type a generic TypeScript?

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.

How do you use generic type as a value in TypeScript?

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.

How do you define an array of different generic types in TypeScript?

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'];


2 Answers

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.

like image 96
Andreas Avatar answered Oct 07 '22 11:10

Andreas


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.

like image 34
Javi Marzán Avatar answered Oct 07 '22 13:10

Javi Marzán