In the deps
array below, I aim to enforce type safety. Only strings allowed should be in dot notation of ${moduleX}.${moduleX service}
// Modules each have a factory function that can return a services object (async)
createModules({
data: {
factory: () => Promise.resolve(() => {
return {
services: {
createResource: () => {}
},
};
})
},
dependentModule: {
deps: ['data.createResource'], // <!-- should allow this
factory: () => Promise.resolve(() => ({}))
},
incorrectConfig: {
deps: ['data.serviceDoesNotExist'], // <-- should error here
factory: () => Promise.resolve(() => ({}))
}
});
function createModules<M>(config: Config<M>) {}
export type Config<M> = {
[K in keyof M]: ModuleConfig<M>
}
export type Config<M> = {
[K in keyof M]: {
deps?: (`${keyof M & string}.${keyof (Awaited<M[keyof M]['factory']>['services']) & string}`)[]
factory: () => Promise<(...args: any) => { services?: { [key: string]: any } }>
}
}
I currently permit data.serviceDoesNotExist
because it's merely inferred as a string
:
deps?: (`data.${string}` | `dependentModule.${string}` | `incorrectConfig.${string}`)[] | undefined
How can I improve the inference to obtain the actual property name?