In the world of TypeScript, I have a scenario that might be a bit tricky, but I'll throw it out there anyway.
Let's say I start with a base service class:
export default class Service {
public static readonly accessorName: string
constructor(protected prisma: PrismaClient, protected services: ServiceMap) {}
}
Now, imagine I have multiple classes that extend this base class:
export default class Users extends Service {
public static readonly accessorName = "users"
}
export default class Warehouses extends Service {
public static readonly accessorName = "warehouses"
}
export default class Depots extends Service {
public static readonly accessorName = "depots"
}
My goal is to create a statically typed object structured like this:
type ServiceMap = {
users: Users
warehouses: Warehouses
depots: Depots
}
Note that each key in ServiceMap
should correspond to the accessorName
property from each class.
I've tried various approaches and got close by organizing the classes in a module and exporting them:
import Users from "./Users"
import Warehouses from "./Warehouses"
import Depots from "./Depots"
export { Users, Warehouses, Depots }
Then, I created a separate ServiceMap
module that imports these services and defines them under a namespace.
import { PrismaClient } from "@prisma/client"
import * as services from "./services"
import { Service } from "./services/Service"
type Services = typeof services
export type ServiceMap = {
[S in keyof Services]: InstanceType<Services[S]>
}
export default function createServiceMap(prisma: PrismaClient) {
const map: Partial<ServiceMap> = {}
Object.values(services).map(
(s: typeof Service) => (map[s.name as keyof ServiceMap] = new s(prisma, map as ServiceMap))
)
return map as ServiceMap
}
However, the resulting type for ServiceMap
turns out to be:
type ServiceMap = {
Users: Users
Warehouses: Warehouses
Depots: Depots
}
Furthermore, using map[s.name as keyof ServiceMap]
triggers an error message saying:
Type 'Service' is not assignable to type 'Users & Warehouses & Depots'.
If feasible, my ultimate aim is to utilize the accessorName
attribute for generating the keys within the ServiceMap
. Is there a way to achieve this?