0

I have an array of types declared as

const APIS = [NewsApi, CommentsApi, FileApi];

I want to have a method that accepts one of these types from that APIS array, like the following:

myMethod<T extends anyof APIS>(apiType: T): T {
    const api = new apiType(); //pseudo code, does not work off course
    // some common configuration code
    return api;
} 

. I cannot do myMethod<T extends NewsApi|CommentsApi>(): T, as the APIS array is auto generated. Is this possible with typescript?

Update:

Aleksey's solution works great for passing in the input. However, the return type cannot be inferred from the usage.

const myApi = myMethod(NewsApi);

In above case, myApi is not of type NewsApi, but NewsApi|CommentsApi|FileApi. Is it possible to set the return type explicitly to instance of input api type?

1 Answer 1

3

If you can change definition of the array to readonly tuple:

const APIS = [NewsApi, CommentsApi, FileApi] as const;

then you can get union of possible array values using lookup type:

type ApiConstructors = typeof APIS[number];

function myMethod<T extends InstanceType<ApiConstructors>>(apiType: new () => T): T {
  return new apiType();
}

const api = myMethod(NewsApi); // api is of type NewsApi

InstanceType utility used to get instance type of a constructor function.

Playground

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you @Aleksey :) . Also, would it be possible to set the return type of the method explicitly to an instance of api type? I understand that the return type will be implicitly inferred from the returned object. Just wondering, if it can also be set explicitly, just in case I am declaring an interface.
Just noticed that the return type is not exactly inferred from the usage. When I declare const myApi = myMethod(NewsApi); myApi is not inferred as NewsApi, but union of all apis.
I'll check this later, but that's not what you've asked originally 🙂
I agree, I should have been more specific in the first place. Sorry for that. :)
@VictorMukherjee I've updated answer and playground

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.