【问题标题】:Typescript generic type T toString打字稿泛型类型 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 添加到参数中。

【问题讨论】:

标签: typescript types


【解决方案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

    【讨论】:

      猜你喜欢
      • 2021-11-26
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2020-06-29
      • 1970-01-01
      • 2020-05-09
      • 2017-09-15
      • 2020-01-23
      相关资源
      最近更新 更多