我正在尝试创建一个在深度嵌套的对象(本例中为theme)中安全地查找属性的函数。值得一提的是,我不想静态地定义它的类型,因为它们旨在成为频繁更改的对象,从而使用typeof
这个函数接受对象本身和3个键,但问题是-我不能正确地推断它们的类型。
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]
}在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; }; }'.看起来不可能查找具有联合类型和中途需要的某种推断的联合类型。
有什么想法吗?
发布于 2019-10-18 23:27:01
我倾向于避免所有的条件类型,因为编译器不能很好地推理它们,而且看起来你也不需要它们。您可以像type Foo<T extends U> = Foo<T>一样使用constrain T,而不是type Foo<T> = T extends U ? F<T> : never,这对编译器来说更简单。
这里的解决方案可能是在足够多的类型参数中创建getStyle() generic,以便编译器能够理解每个参数都是向下钻取到一个对象中,并对其属性进行looking up。如下所示:
const getStyle = <
K extends keyof Theme,
S extends keyof Theme[K],
M extends keyof Theme[K][S]
>(t: Theme, name: K, style: S, mod: M) => t[name][style][mod];这里我们说t是Theme类型,name是某种被约束为keyof Theme的泛型类型K,style是被约束为keyof Theme[K]的某种泛型类型S,而mod是被约束为D18的某种泛型类型。这允许t[name][style][mod]无错误地编译,并且getStyle()的返回类型被推断为Theme[K][S][M],这意味着输出也将是强类型的:
const sm = getStyle(theme, "button", "margin", "sm"); // string
const lg = getStyle(theme, "form", "padding", "lg"); // string好吧,希望这能帮上忙。祝你好运!
https://stackoverflow.com/questions/58452055
复制相似问题