Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Infer parameters from return type of generic

I’m creating a function whereby the first parameter is an array of "services", and the second parameter infers the return type of those services. For example:

const serviceOne = createService([], () => Promise.resolve({} as Service1));
const serviceTwo = createService([], () => Promise.resolve({} as Service2));

const serviceThree = createService(
  [serviceOne, serviceTwo],
  (one, two) => Promise.resolve({}), // one should be inferred as Service1, two should be inferred as Service2
);

How can I modify my function signature to achieve this inference? At the moment, I have them typed as any

function createService<T extends Service<any>[], U>(deps: T, factory: (...args: any[]) => Promise<U>) {
  return {} as Service<U>;
}

type Service<U> = {
  instance: U
};

Playground

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You can first need to change the constraint to T to get typescript to infer a tuple type instead of an array type. To do this, we just need to add a union with the empty tuple to the constraint ([] |). This will set typescript in the right state to infer tuples

We can then use a mapped type to map from a tuple containing Service<any> to a tuple containing the service types:

const serviceThree = createService(
  [serviceOne, serviceTwo],
  (one, two) => Promise.resolve({} as Service3), // one is Service1, two is Service2
);

type GetServiceType<T extends Service<any>[]> = unknown [] & {
  [P in keyof T]: T[P] extends Service<infer R> ? R: never
}
function createService<T extends [] | Service<any>[], U>(deps: T, factory: (...args: any[] & GetServiceType<T>) => Promise<U>) {
  return {} as Service<U>;
}

Playground Link

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading