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

2023-12-11

我正在尝试创建一个函数来安全地查找深层嵌套对象中的属性(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; }; }'.

看起来不可能用联合类型查找联合类型,并且中途需要某种推理。

有任何想法吗?


我倾向于避免所有条件类型,因为编译器无法很好地推理它们,并且看起来您不需要它们。代替type Foo<T> = T extends U ? F<T> : never,你可以只是约束 T, like type Foo<T extends U> = Foo<T>,这对于编译器来说更简单。

这里的解决方案可能是getStyle() generic有足够多的类型参数,编译器可以理解每个参数都深入到一个对象中,并且抬头看它的属性。像这样:

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, that name属于某种通用类型K限制于keyof Theme, that style属于某种通用类型S限制于keyof Theme[K], 然后mod属于某种通用类型M限制于keyof Theme[K][S]。这允许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

好的,希望有帮助。祝你好运!

链接到代码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

推断 Typescript 中深度嵌套对象的类型 的相关文章

  • 为什么 TypeScript 将类打包在 IIFE 中?

    这是一个 TypeScript 类 class Greeter public static what string return Greater public subject string constructor subject strin
  • Java 8 中异常类型推断的一个独特功能

    在为该网站上的另一个答案编写代码时 我遇到了这个特性 static void testSneaky final Exception e new Exception sneakyThrow e no problems here nonSnea
  • Typescript + Jquery Ajax + 这个

    我正在将一些 javascript 代码移植到 typescript 中 但遇到了一个问题 我有一个 ajax 调用 它将一个对象作为上下文传递 该对象包含一些回调和一些其他信息 这些信息由成功或错误回调读出 指示成功调用应重定向到的位置
  • 如何使用 useState 挂钩按索引更新数组?

    我有一个选择组件 我想用它来根据索引更新对象数组的值 我这样使用钩子 const areas setAreas useState product areas 这将返回以下 区域 0 de Getraenke en Drinks 1 de S
  • TypeScript 中类和命名空间的区别

    到底有什么区别classes and namespaces在打字稿中 我知道 如果您创建一个带有静态方法的类 您可以在不实例化该类的情况下访问它们 这正是我猜想的命名空间的要点之一 我还知道你可以创建多个同名的命名空间 并且它们的方法在编译
  • 定义文件:属性的多种可能类型

    我正在为现有的 JS 库 CKEditor 编写一些定义 是否可以更具体toolbar any 文档 工具栏 数组 字符串 工具箱 别名工具栏 定义 它是工具栏名称或 工具栏 条 数组 每个工具栏也是一个数组 包含一个 UI 项目列表 库代
  • 为什么类型参数不被推断为联合类型?

    这段代码 declare function fn
  • 修改对象实例的 TypeScript 类装饰器

    我正在为 Aurelia 制作一个插件 需要一个类装饰器 将属性添加到新对象实例 并且 使用新对象作为参数调用外部函数 我已经查看了示例 到目前为止我已经将它们放在一起 伪 代码 return function addAndCall tar
  • 在 Nest.js 中发送之前如何格式化响应?

    我按照文档进行操作 并能够添加用于响应映射的拦截器 我想要一致的 json 格式输出作为响应 我怎样才能用拦截器或其他比这种方法更好的方法来实现这一点 statusCode 201 message Custom Dynamic Messag
  • Gulp 和 TS 编译

    我在我的 gulp 文件中定义了任务 gulp task dev build scripts function var tsResult tsProject src pipe sourcemaps init pipe ts tsProjec
  • 尝试为每一行编写测试用例

    已经编写了跳跃方法的测试用例 但当我看到代码覆盖率报告时 它不会进入onloadend方法seat onloadend 在 createSpyObj 中我调用了 loadend 但它仍然没有进入内部 你们能告诉我如何解决它吗 下面提供我的代
  • `Account` 是 TypeScript 中的保留字吗?

    我很困惑 以下 TypeScript 代码无法编译并出现此错误 fails ts 10 7 error TS2420 Class Account incorrectly implements interface IAccount Prope
  • 将 Meteor.js 中的模块与 Typescript 一起使用

    各位 我正在尝试做一些我认为应该很简单的事情 但我一定做错了 我试图在使用 Typescript 的流星应用程序中简单地拥有一个清晰的结构 这是我的要求 所有接口在客户端和服务器端均可用 有些类的实现只能在服务器上使用 我不想依赖文件加载顺
  • React 应用程序 npm 错误代码 ELIFECYCLE

    下面是我的反应应用程序 我尝试过重新安装node module 设置 环境变量 C Windows System32 name my app version 0 1 0 private true dependencies testing l
  • 根据多列中的单元格查找匹配行值的公式

    我试图在同一行中 col1 col2 和 col3 各自匹配时查找 col4 值 我参考了这个SO Post https i stack imgur com YDaBP png因为这是一个类似的问题 但该解决方案对我不起作用 我正在寻找具体
  • 如何在 Angularfire2 Angular2 中对 FirebaseListObservable 列表进行排序?

    我想从 Firebase 实时数据库中获取所有用户 并按分数属性对它们进行排序 我已经使用变量来完成这个工作 users FirebaseListObservable
  • minLength 在打字稿中不起作用,反应

    我在 下一步 中有一个输入 打字稿 Maxlength 确实有效 但 minlength 现在不起作用 有人如何验证这两者吗 这是我的代码
  • 从 *ngIf Angular 5 调用函数

    假设我这里有这段代码 div lorem ipsum div 如果 ngIf 计算结果为 true 有没有办法可以调用函数 你知道这样的事情 div lorem ipsum div 任何帮助 将不胜感激 Thanks 角度方式是 div d
  • 如何在 TS 中使用泛型谓词

    我想使用数组过滤谓词函数 e g const isNotEmptyName
  • Unraveling Angular 2 书,第 1 章,示例 5

    该页面显示了潜水列表 它有一个 添加新潜水 清除潜水 和一个搜索框 该搜索框会在您输入内容时过滤显示的列表 这是模板 div class container fluid h1 My Latest Dives Angular TypeScri

随机推荐