简体   繁体   English

打字稿泛型类型 T toString

[英]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.在泛型方法或类中,我想记录已使用的泛型 T 类型的名称,我需要将其作为字符串。

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.上面的getTypeName是错误的,它甚至不会构建。 typeof would be transpiled in JS and wouldn't produce the desired effect. typeof 将在 JS 中转译并且不会产生预期的效果。 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.此外,该方法不是通用的,因为如果您尝试传入具有构造函数参数的类型,它将显示错误:“ [ts] 类型为 'typeof MyType' 的参数不可分配给类型为 'new () => MyType 的参数'. " 此外,如果您在泛型方法中使用该函数,则不能将 T 用作参数,这意味着在需要从泛型 Type 中获取名称的任何地方,我都需要将 ctor 添加到参数中。

Using the answer here , I adapted it to better cover my needs, but still, this is not my full answer, because even dough it works, compiles and the tests passes, the following code shows an error in VS and VS Code.使用这里的答案,我对其进行了修改以更好地满足我的需求,但是,这仍然不是我的完整答案,因为即使面团可以工作,编译并且测试通过,以下代码显示了 VS 和 VS Code 中的错误。

The helper class:辅助类:

export class TypeHelper {

    static typeName(ctor: { name:string }) : string {
        return ctor.name;
    }
}

The test class (Jasmine spec):测试类(茉莉花规范):

import { TypeHelper } from './../util/TypeHelper';

class MyClass {
    public MyGenericMethod<T>(): string {
        let iNeedTheTypeNameHere = TypeHelper.typeName(T);
        return `Use the string here somehow: ${iNeedTheTypeNameHere}`;
    }
}
describe("TypeHelper", () => {
    describe("TypeHelper", () => {
        it("typeName, returns the string type name of the Class passed as parameter", () => {
            let t = TypeHelper.typeName(TypeHelper);
            expect(t).toBe("TypeHelper");
            let m = TypeHelper.typeName(MyClass);
            expect(m).toBe("MyClass");
        });

        it("typeName, returns the string type name of a generic type T passed as parameter", () => {
            let myClass = new MyClass();
            let t = myClass.MyGenericMethod<TypeHelper>();         
            expect(t).toBe("TypeHelper");
            let m = myClass.MyGenericMethod<MyClass>();     
            expect(m).toBe("MyClass");
        });
    });
});

The error: [ts] 'T' only refers to a type, but is being used as a value here.错误:[ts] 'T' 仅指一种类型,但在此处用作值。

I'm not a TS expert but I will keep looking into this to try to understand how to solve this issue.我不是 TS 专家,但我会继续研究这个问题以尝试了解如何解决这个问题。

EDIT: Added playground example编辑:添加操场示例

Well, Generics in TypeScript is just a construct that helps in typechecking.好吧,TypeScript 中的泛型只是一种有助于类型检查的构造。 "T" is in fact "nothing" - it's nothing that can be transpiled into JavaScript. “T”实际上是“无”——它不能被转换成 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.无论如何,您需要做的是提供一些 JavaScript 对象。 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.但是在这里您提供了一个真正的 JavaScript 对象,而不仅仅是一个 TypeScript 类型名称。 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:在搜索了所有互联网,制作了我自己的装饰器并摆弄了很多 Typescript 之后,我被这篇文章绊倒了:

Get an object's class name at runtime 在运行时获取对象的类名

Basically, you can use Message.name as long as Message is a class.基本上,只要Message是一个类,您就可以使用Message.name

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM