You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript高级类型:如何提取嵌套对象中所有id字段的值?

问题原因分析

你的NestedId类型失效的核心问题在于联合类型的键处理逻辑错误,以及递归范围的局限性:

  1. 联合类型的keyof取交集导致递归中断
    当处理children数组的元素时,ObjectType[Key][number]是三个对象的联合类型:{ id: "two" } | { id: "three"; children: [...] } | { abc: "def" }。TypeScript中keyof (A | B | C)会返回所有成员键的交集,而这三个对象没有公共键,因此keyof结果为never,映射类型{[Key in ...]: ...}为空,最终递归调用返回never,嵌套的id值完全丢失。
  2. 递归仅针对children键,逻辑覆盖不全
    原实现只对children键做递归处理,没有考虑对象其他键下可能的嵌套结构,且没有利用TypeScript的分布式条件类型来自动拆分联合类型并逐个处理。
解决方法

可以通过两种方式修复,一种是针对你的原逻辑调整,另一种是实现更通用的全层级id提取类型:

方式一:修复原逻辑(适配children结构)

修改递归逻辑,让联合类型能被正确拆分处理,利用分布式条件类型对每个数组元素单独递归:

type ExampleType = {
  id: "one"
  children: [{ id: "two" }, { id: "three"; children: [{ id: "four" }] }, { abc: "def" }]
  efg: "hij"
}

// 先处理联合类型的分发,用裸类型参数触发分布式条件类型
type NestedId<T> = T extends Record<string, any> | undefined 
  ? {
      [Key in keyof T & string]: T[Key] extends undefined
        ? never
        : Key extends "id"
          ? T[Key]
          : Key extends "children"
            ? T[Key] extends Array<infer U>
              ? NestedId<U> // 对数组元素类型单独递归,触发联合分发
              : never
            : never
    }[keyof T & string]
  : never

const id1: NestedId<ExampleType> = "one" // 正常
const id2: NestedId<ExampleType> = "two" // 正常
const id3: NestedId<ExampleType> = "three" // 正常
const id4: NestedId<ExampleType> = "four" // 正常
const foo: NestedId<ExampleType> = "foo" // 报错(符合预期)
const bar: NestedId<ExampleType> = "bar" // 报错(符合预期)

方式二:通用全层级id提取类型(推荐)

如果需要提取任意嵌套结构(不仅限于children数组)中的所有id值,可以实现更通用的类型,自动遍历所有嵌套层级:

type ExampleType = {
  id: "one"
  children: [{ id: "two" }, { id: "three"; children: [{ id: "four" }] }, { abc: "def" }]
  efg: "hij"
}

type NestedId<T> = 
  // 过滤空值类型
  T extends undefined | null ? never :
  // 提取当前对象的id(如果存在),并递归处理所有值
  T extends { id: infer Id } ? Id | NestedId<Exclude<T[keyof T], undefined | null>> :
  // 处理数组,递归处理元素类型
  T extends Array<infer U> ? NestedId<U> :
  // 处理其他对象,递归处理所有值
  T extends object ? NestedId<Exclude<T[keyof T], undefined | null>> :
  // 非对象/数组类型返回never
  never

const id1: NestedId<ExampleType> = "one" // 正常
const id2: NestedId<ExampleType> = "two" // 正常
const id3: NestedId<ExampleType> = "three" // 正常
const id4: NestedId<ExampleType> = "four" // 正常
const foo: NestedId<ExampleType> = "foo" // 报错(符合预期)
const bar: NestedId<ExampleType> = "bar" // 报错(符合预期)

这个通用版本通过分布式条件类型自动拆分联合类型,遍历所有嵌套对象和数组,提取所有层级的id值,适用性更广。

内容的提问来源于stack exchange,提问作者David Alvarez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:04:57