Reputation: 114817
My goal is to have a function that takes a key and an object with query parameters and the function can look up a URL, interpolate with the query params and navigate to that. What I got so far is this
interface FooIdParams {
fooId: number;
}
interface QueryParams<P = never> {
params: P;
}
enum Urls {
'foo-editor' = '/editfoo?fooId=${fooId}'
}
interface ParamTypes {
'foo-editor': QueryParams<FooIdParams>
}
and the load method in my class looks like this:
load = <T extends keyof ParamTypes>(target: T, params: ParamTypes[T]["params"]):void => {
const url = eval('`' + Urls[target] + '`')
// alternative with replace like suggested in a comment
// this also works with multiple query params
const url2 = Urls[target].replaceAll(/\$\{(.*?)\}/g, (_: string, k: string) => (params as any)[k])
// and some code to open that page
}
This already works and ensures that the called provides correct query params (later I have dozens of URL targets and the load method is called from many places, so it's worth the effort)
The part that I can't solve: I use the key foo-editor
in two different places, the enum where it maps to the 'url' and in the interface, where it maps to the type. And I'd like to guarantee, that both enum and interface have exactly the same keys (like - typescript should force to mappings in both and prevent typos).
Is there a way to ensure that?
Upvotes: 2
Views: 277
Reputation: 138537
You could replace the enum with a mapped type:
const Urls: { [K in keyof ParamTypes]: string } = {
/*...*/
};
Upvotes: 3