我有一个常量的树状对象来建模嵌套关系,并且正在try 构建一个类型,该类型通过父对象的固定属性为这些关系设置关键字;也就是说,我想获取以下内容:

const tree = {
    label: 'root',
    leaves: [
        {
            label: 'root.a',
        },
        {
            label: 'root.b',
            leaves: [
                {
                    label: 'root.b.a',
                },
            ],
        },
        {
            label: 'root.c',
            leaves: [
                {
                    label: 'root.c.a',
                },
                {
                    label: 'root.c.b',
                    leaves: [
                        {
                            label: 'root.c.b.a',
                        },
                    ],
                },
            ],
        },
    ],
} as const

并推断出如下文字类型:

type KeyedTree = {
  "root.a": {},
  "root.b": {
    "root.b.a": {}
  },
  "root.c": {
    "root.c.a": {},
    "root.c.b": {
      "root.c.b.a": {}
    }
  }
}

我到目前为止try 过的示例代码:TypeScript playground.

我设法让类型在特定 node 是否包含子 node 的情况下进行测试,如果包含子 node ,则生成具有正确字符串字面键的Record类型,但我正在努力将其扩展为遍历整个对象以捕获嵌套 struct (并迭代 node ,而不是使用对索引的硬编码引用).

我觉得它应该像在子 node 上递归地应用MaybeTree类型一样简单(例如,在运行时参见操场链接的底部)--但我还没有找到一种方法来将其转换到类型系统中.

推荐答案

首先,让我们给出tree的类型,我们可以用作constraint:

type Tree = { label: string; leaves?: readonly Tree[] };

然后,我们可以编写递归ToKeyedTree<T>实用程序类型,将输入T extends Tree转换为您想要的形式,如下所示:

type ToKeyedTree<T extends Tree> =
    T["leaves"] extends readonly Tree[] ? {
        [L in T["leaves"][number] as L["label"]]: ToKeyedTree<L>
    } : {}

这里的方法是使用key remapping迭代访问T‘S leaves属性的元素类型L,假设它存在(我们使用conditional type进行判断,如果不存在则返回{}).对于每个这样的元素L,我们希望添加一个具有键L["label"]和值ToKeyedTree<L>的属性.


让我们确保它与您的示例一起工作:

type KeyedTree = ToKeyedTree<typeof tree>;
/* type KeyedTree = {
    "root.a": {};
    "root.b": {
        "root.b.a": {};
    };
    "root.c": {
        "root.c.a": {};
        "root.c.b": {
            "root.c.b.a": {};
        };
    };
} */

看上go 不错.

Playground link to code

Typescript相关问答推荐

如何使用Generics保留构造函数的类型信息?

类型脚本不会推断键的值类型

typescript抱怨值可以是未定义的,尽管类型没有定义

动态调用类型化函数

为什么TypeScript失go 了类型推断,默认为any?''

在MessageStore对象中实现条件类型时出现TypeScrip错误

适当限制泛型函数中的记录

在Reaction-Native-ReAnimated中不存在Animated.Value

ApexCharts条形图未显示最小值.负值

函数重载中的不正确TS建议

是否将自动导入样式从`~/目录/文件`改为`@/目录/文件`?

如何从MAT-FORM-FIELD-MAT-SELECT中移除焦点?

在类型脚本中将泛型字符串数组转换为字符串字母并集

如何在脚本中输入具有不同数量的泛型类型变量的函数?

在组件卸载时try 使用useEffect清除状态时发生冲突.react +打字

如何在打字角react 式中补齐表格组

为什么TypeScrip假定{...省略类型,缺少类型,...选取类型,添加&>}为省略类型,缺少类型?

对于VUE3,错误XX不存在于从不存在的类型上意味着什么?

如何使用 AWS CDK 扩展默认 ALB 控制器策略?

如何确定剧作家中给定定位器的值?