【问题标题】:Using a generic type argument with `typeof T`使用带有 `typeof T` 的泛型类型参数
【发布时间】:2018-03-07 02:10:32
【问题描述】:

我有一个类似工厂的函数,旨在返回BaseApi 的子类实例。它目前看起来像这样(删除了不相关的部分):

function getApi<T extends BaseApi>(apiClass: typeof BaseApi): T {
    return new apiClass();
}

我是这样使用它的:

const someApi = getApi<SomeApi>(SomeApi);

这行得通,但我希望 &lt;SomeApi&gt; 能够通过我传递 SomeApi 构造函数的事实来推断。如果我省略 &lt;SomeApi&gt;someApi 被推断为 @ 类型987654328@,不是SomeApi。更糟糕的是,&lt;T extends BaseApi&gt;typeof BaseApi 之间实际上没有编译器相关性,因为它们是同一件事,因此您可以错误地执行类似 getApi&lt;SecondApi&gt;(FirstApi) 的操作而不会出现编译器错误。

所以我尝试将apiClass 定义为typeof T

function getApi<T extends BaseApi>(apiClass: typeof T): T {
    return new apiClass();
}

我发现TS不理解T的这种用法。有没有办法做到这一点?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您真正想要的是new() =&gt; T,因为您打算将参数用作构造函数并生成T。即使你可以写typeof T,那也不是你想要的,因为T 可能没有零参数构造函数。

    请记住,typeof 运算符采用 value 并产生 valueT 已经是一个类型;这不是一个值。

    当然,这已在 TypeScript 常见问题解答https://github.com/Microsoft/TypeScript/wiki/FAQ#why-cant-i-write-typeof-t-new-t-or-instanceof-t-in-my-generic-function 中得到解决

    【讨论】:

    • 在使用无参数构造函数和带参数的构造函数的情况下,您需要将new() =&gt; T 更新为new (...args)=&gt;T,否则会出现编译错误。
    • 也许这应该是一个单独的问题,但是如果我的T 扩展了一个基类(因为我使用了&lt;T extends BaseClass&gt;),并且BaseClass 有一个像myStaticMethod() 这样的公共静态方法怎么办?我想打电话?是否可以让 typescript 意识到我不仅希望我的变量是一个(0-arg)构造函数(new() =&gt; T),而且我还希望能够在其上调用myStaticMethod()
    • @NicolasB 在这种情况下为什么不arg: { new(): T; myStaticMethod(): any; }
    • @Arad 我认为你写的完全正确,它回答了我的问题。但是,如果基类中有许多具有详细类型的静态方法,则它不能很好地扩展。我想了更多,我认为可行的选项是:arg: (new() =&gt; T) &amp; typeof BaseClass;。交集类型的第一部分负责构造函数部分,第二部分负责静态方法。
    猜你喜欢
    • 1970-01-01
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 2020-08-22
    • 1970-01-01
    相关资源
    最近更新 更多