使用`typeof T`的泛型类型参数

Aar*_*all 11 typescript

我有一个类似工厂的函数,用于返回一个子类实例BaseApi.它目前看起来像这样(修剪掉不相关的部分):

function getApi<T extends BaseApi>(apiClass: typeof BaseApi): T {
    return new apiClass();
}
Run Code Online (Sandbox Code Playgroud)

我这样使用它:

const someApi = getApi<SomeApi>(SomeApi);
Run Code Online (Sandbox Code Playgroud)

这是有效的,但我想<SomeApi>通过我传递SomeApi构造函数的事实来推断.如果我省略<SomeApi>那么someApi推断是类型BaseApi,而不是SomeApi.更糟糕的是,实际上没有编译器相关性,<T extends BaseApi>并且typeof BaseApi是同一个东西,所以你可能会错误地做一些getApi<SecondApi>(FirstApi)没有编译器错误的事情.

所以我尝试定义apiClasstypeof T:

function getApi<T extends BaseApi>(apiClass: typeof T): T {
    return new apiClass();
}
Run Code Online (Sandbox Code Playgroud)

我发现TS不明白这种用法T.有没有办法做到这一点?

Rya*_*ugh 17

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

请记住,typeof运算符获取并生成.T已经是一种类型; 它不是一个价值.

当然,这在TypeScript FAQ中得到解决https://github.com/Microsoft/TypeScript/wiki/FAQ#why-cant-i-write-typeof-t-new-t-or-instanceof-t-in-my -generic功能

  • 也许这应该是一个单独的问题,但是如果我的“T”扩展了一个基类(因为我使用了“&lt;T extends BaseClass&gt;”),并且“BaseClass”有一个我想要的公共静态方法,如“myStaticMethod()”,该怎么办打电话?是否可以让打字稿意识到这样一个事实:我不仅希望我的变量是一个(0-arg)构造函数(`new() =&gt; T`),而且我还希望能够调用`myStaticMethod() ` 就在上面? (4认同)
  • @Arad我认为你写的完全正确,它回答了我的问题。但是,如果基类中有许多具有详细类型的静态方法,那么它的扩展性就不会很好。我想了一些,我认为一个有效的选项是:`arg: (new() =&gt; T) &amp; typeof BaseClass;`。交集类型的第一部分负责构造函数部分,第二部分负责静态方法。 (3认同)
  • https://www.typescriptlang.org/docs/handbook/generics.html#using-class-types-in-generics (2认同)
  • 在使用无参数构造函数和带参数的构造函数的情况下,需要将new()=&gt; T`更新为`new(... args)=&gt; T`,否则会出现编译错误。 (2认同)
  • @NicolasB 为什么不 `arg: { new(): T; myStaticMethod():任意;}` 在这种情况下? (2认同)