I'm trying to create a function that safely looks up the property in deeply nested object (theme
in this case). I should mention that I don't want to statically define its type because they are intended to be a subject to frequent change and thus use typeof
This functions accepts the object itself and 3 keys, but the problem is — I can't correctly infer types for all of them.
const theme = {
button: { margin: { sm: "sm" } },
form: { padding: { lg: "lg" } }
}
type Theme = typeof theme
type CompoName = keyof Theme;
// styles of component with give key
// { margin: ..., padding: ... }
type CompoStyle<C> = C extends CompoName ? keyof Theme[C] : never;
// string
// S = margin, padding
type CompoStyleMod<C, S> = S extends keyof CompoStyle<C>
? CompoStyle<C>[S]
: never;
const getStyle = (
t: Theme,
name: CompoName,
style: CompoStyle<typeof name>,
mod: CompoStyleMod<CompoName, typeof style>
) => {
return t[name][style][mod]
}
The result of this in TypeScript 3.6.3:
Element implicitly has an 'any' type because expression of type '"margin" | "padding"' can't be used to index type '{ margin: { sm: string; }; } | { padding: { lg: string; }; }'.
Property 'margin' does not exist on type '{ margin: { sm: string; }; } | { padding: { lg: string; }; }'.
Looks like it is not possible to look up union types with union types and some kind of inference required midway.
Any ideas?