Using a generic type argument with `typeof T`

Typescript

Typescript Problem Overview


I have a factory-like function that is meant to return an sub-class instance of BaseApi. It currently looks something like this (trimmed out irrelevant parts):

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

And I use it like this:

const someApi = getApi<SomeApi>(SomeApi);

This works, but I would like <SomeApi> to be inferred by virtue of the fact that I'm passing the SomeApi constructor in. If I omit <SomeApi> then someApi is inferred to be of type BaseApi, not SomeApi. Worse, there's really no compiler correlation between <T extends BaseApi> and typeof BaseApi being the same thing, so you can incorrectly do something like getApi<SecondApi>(FirstApi) without a compiler error.

So I tried defining the apiClass as typeof T:

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

And I found that TS did not understand this usage of T. Is there any way to do this?

Typescript Solutions


Solution 1 - Typescript

What you actually want is new() => T, since you intend to use the argument as a constructor and produce a T. Even if you could write typeof T, that wouldn't be what you want, since T might not have a zero-argument constructor.

Remember that the typeof operator takes a value and produces a value. T is already a type; it is not a value.

Naturally, this is addressed in the TypeScript FAQ https://github.com/Microsoft/TypeScript/wiki/FAQ#why-cant-i-write-typeof-t-new-t-or-instanceof-t-in-my-generic-function

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAaron BeallView Question on Stackoverflow
Solution 1 - TypescriptRyan CavanaughView Answer on Stackoverflow