Home > Software design >  Utilize keyof to determine return type automatically
Utilize keyof to determine return type automatically

Time:07-17

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>'
}

Playground

  • Related