I can't decide on a name for this concept, so please be patient while I explain it.
There are three configuration objects:
const configA = {
type: 'A' as const,
getPath: (query: { foo: string }) => `/${query.foo}`
}
const configB = {
type: 'B' as const,
getPath: (query: {}) => `/path/b`
}
const configC = {
type: 'C' as const,
getPath: (query: {bar: number}) => `/c/${query.bar}`
}
These configurations are combined into a master record like this:
const CONFIGS = {
[configA.type]: configA,
[configB.type]: configB,
[configC.type]: configC
}
Now, the goal is to write a function that enforces type safety based on these configurations. For example, if the following code is written:
add({
type: 'C',
query: { foo: true }
})
TypeScript should warn about the invalidity of the query
object when the type
is C
. However, currently no warning is issued.
An attempt was made with the following implementation:
function add(inputs: {
type: (typeof CONFIGS)[keyof typeof CONFIGS]['type'],
query: Parameters<(typeof CONFIGS)[keyof typeof CONFIGS]['getPath']>[0]
}) {
const config = CONFIGS[inputs.type];
if (!config) {
throw new Error('Config not found');
}
const url = 'mysite.blah' + config.getPath(inputs.query);
console.log('url:', url);
}
Unfortunately, this code isn't working as intended and gives a TypeScript error related to the inputs.query
:
Argument of type '{} | { foo: string; } | { bar: number; }' is not assignable to parameter of type '{ foo: string; } & { bar: number; }'.
The complete code is available in the TypeScript Playground.
What is this approach called, and is there a way to resolve this issue? Thank you.