'TypeScript Mapped Type - Convert type properties to instances of type
I am trying to convert an object full of class constructors to a mapped object with properties that are functions that return an instance.
For example:
// From an external auto-generated utility:
class FooClient { getData() {}}
class BarClient { getData() {}}
export const Clients = {
FooClient,
BarClient
}
Which can be consumed:
import { Clients } from './somemodule';
type ClientTypes = typeof Clients;
function getFooData(c: ClientTypes) {
const fooClient = new c.FooClient();
return fooClient.getData();
}
What I am shooting for is to replace the classes / constructors with factory functions:
type Factories = {
[Property in keyof ClientTypes as `use${Property}`]: () => ClientTypes[Property]
}
function getFooData(f: Factories) {
const fooClient = new (f.useFooClient()); // <-- use function returns the original constructor type
return fooClient.getData();
}
My question is, how can I change the return type on the mapped type such that it does not return a constructor, but rather, I want it to return the value as if the constructor had been called.
For example:
function getFooData(f: Factories) {
const fooClient = f.useFooClient(); // <-- returns an instance instead
return fooClient.getData();
}
Is there some kind of keyword that can indicate that I want my function to return an instance of a type instead of the type itself?
Solution 1:[1]
You were close, however, when you were typing the return type of use_ you returned the class type. However, you need to do a little bit more work to make it act as a regular function that returns a class instead of a constructor. You can do this by creating a new function that returns InstanceType<ClientTypes[Property]>.
class FooClient { getData() {}}
class BarClient { getData() {}}
export const Clients = {
FooClient,
BarClient
}
type ClientTypes = typeof Clients;
type Factories = {
[Property in keyof ClientTypes as `use${Property}`]: () => InstanceType<ClientTypes[Property]>
}
function getFooData(f: Factories) {
const fooClient = f.useFooClient();
return fooClient.getData();
}
If you wanted to include constructor parameters in this callback, then add a rest parameter to the function type with the type of ConstructorParameters<ClientTypes[Property]>.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | nicholas |
