I have an interface as follows
interface ResourceState<ItemType> {
rows: ItemType[],
store: Record<String, ItemType>
}
And I create a root state as follows
RootState{
car: ResourceState<Car>
user: ResourceState<User>
}
I defined a service as a function that accepts the id and returns an instance of the resource (via an API, random generator or something else)
type Service<Resource>=(id: string)=> Promise<Resource>
I want to define a mapping which tells the system how to load the resource for any of the items in the RootState
export const storeServicesMapping : Record<keyof RootState, Service<???> >={
"user": (id:string)=>Promise.resolve({} as User)//should work
"car": (id:string)=>Promise.resolve({} as User)//should not work, it should expect Service<Car>
}
So based on the key from the root state, it should decide the type of the service.
CodePudding user response:
You can generate all possible key/Service<key>
combinations with a mapped type.
type StoreServicesMapping = {
[K in keyof RootState]:
Service<RootState[K] extends ResourceState<infer U>
? U
: never
>
}
For each key K
in RootState
this will add a property to the resulting type with the key K
and the corresponding Service
type. For the Service
type, you can get the ItemType
out of the ResourceState
with infer
.
export const storeServicesMapping : StoreServicesMapping = {
"user": (id:string)=>Promise.resolve({} as User),
"car": (id:string)=>Promise.resolve({} as User) // Error: 'Promise<User>' is not assignable to type 'Promise<Car>'
}