首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >推断Typescript中深度嵌套对象的类型

推断Typescript中深度嵌套对象的类型
EN

Stack Overflow用户
提问于 2019-10-18 21:38:14
回答 1查看 1.1K关注 0票数 1

我正在尝试创建一个在深度嵌套的对象(本例中为theme)中安全地查找属性的函数。值得一提的是,我不想静态地定义它的类型,因为它们旨在成为频繁更改的对象,从而使用typeof

这个函数接受对象本身和3个键,但问题是-我不能正确地推断它们的类型。

代码语言:javascript
复制
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中的结果是:

代码语言:javascript
复制
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; }; }'.

看起来不可能查找具有联合类型和中途需要的某种推断的联合类型。

有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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。如下所示:

代码语言:javascript
复制
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];

这里我们说tTheme类型,name是某种被约束为keyof Theme的泛型类型Kstyle是被约束为keyof Theme[K]的某种泛型类型S,而mod是被约束为D18的某种泛型类型。这允许t[name][style][mod]无错误地编译,并且getStyle()的返回类型被推断为Theme[K][S][M],这意味着输出也将是强类型的:

代码语言:javascript
复制
const sm = getStyle(theme, "button", "margin", "sm"); // string
const lg = getStyle(theme, "form", "padding", "lg"); // string

好吧,希望这能帮上忙。祝你好运!

Link to code

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58452055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档