打字稿泛型类型 T toString

Posted

技术标签:

【中文标题】打字稿泛型类型 T toString【英文标题】:Typescript generic type T toString 【发布时间】:2018-04-27 16:57:28 【问题描述】:

我认为不可能,但值得一问。 在泛型方法或类中,我想记录已使用的泛型 T 类型的名称,我需要它作为字符串。

想象一个这样的方法:

static getTypeName<T>(): string 
    return typeof T; // This is wrong

我希望能够以这种方式使用它:

let m = getTypeName<Message>(); // Expected string "Message"
let p = getTypeName<Person>();  // Expected string "Person"

上面的 getTypeName 是错误的,它甚至不会构建。 typeof 会在 JS 中转译,不会产生预期的效果。 我尝试了各种方法,但都没有成功。

有什么方法可以实现吗?

编辑:为什么这不是重复的:this question

问题和示例代码显示了如何取回对象而不是指定类型的名称。 该方法也不是通用的,因为如果您尝试传入具有构造函数参数的类型,它将显示错误: “[ts] 'typeof MyType' 类型的参数不能分配给 'new () => MyType' 类型的参数。” 此外,如果您在泛型方法中使用该函数,则不能使用 T 作为参数,这意味着我需要从泛型类型中获取名称的任何地方,都需要将 ctor 添加到参数中。

【问题讨论】:

相关:***.com/questions/41160690/… Is it possible to get the type name of a generic type?的可能重复 【参考方案1】:

在搜索了所有的互联网、制作自己的装饰器并大量摆弄 Typescript 之后,我被这篇文章绊倒了:

Get an object's class name at runtime

基本上,只要Message 是一个类,您就可以使用Message.name

但是要小心,因为如果在进行生产构建时类名被缩小,这可能会停止工作,所以在使用这种方法之前请检查。

【讨论】:

【参考方案2】:

嗯,TypeScript 中的泛型只是一种有助于类型检查的构造。 “T”实际上是“无”——它没有什么可以转译成 javascript。但是你需要这个构造函数来获取你的类型名称。这就是您收到该错误消息的原因。您只提供了一个类型,但需要一个值(具有该构造函数)才能使您的代码正常工作。


编辑:

无论如何,您需要做的是提供一些 JavaScript 对象。这样的事情会起作用:

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"

但是在这里你提供了一个真正的 JavaScript 对象,而不仅仅是一个 TypeScript 类型名称。这就是它起作用的原因。

【讨论】:

安德烈亚斯,鉴于你所说,有没有这样的解决方案来做我需要的?还是不可能? @Manuel:您在最初的问题中要求的内容是不可能的。有关详细信息,请参阅我编辑的答案【参考方案3】:

使用答案here,我对其进行了调整以更好地满足我的需求,但这仍然不是我的完整答案,因为即使它可以工作,编译并且测试通过,以下代码在VS中显示错误和VS 代码。

助手类:

export class TypeHelper 

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

测试类(Jasmine 规范):

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");
        );
    );
);

错误: [ts] 'T' 仅指一种类型,但在这里用作值。

我不是 TS 专家,但我会继续研究以尝试了解如何解决此问题。

编辑:添加playground example

【讨论】:

以上是关于打字稿泛型类型 T toString的主要内容,如果未能解决你的问题,请参考以下文章

打字稿泛型返回类型

打字稿泛型,获取数组内容的类型

打字稿泛型:从函数参数的类型推断类型?

带有约束的打字稿泛型不能分配给泛型接口

难以理解的打字稿泛型函数重载

如何在打字稿的泛型类中创建类型为“T”的新对象?