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

如何在TypeScript中提取类型的所有字符串属性(含嵌套路径)

提取嵌套对象中符合类型条件的属性路径

假设我们有如下类型:

type Foo = {
    a : number
    b : string
    c : number
    d : string
}

我们希望构造一个类型,比如type Bar = AllStringAttributes<Foo>,让它返回如下新类型:

type Bar = {
    b : string
    d : string
}

这种场景可以通过以下类型实现:

type KeysOfValue<T, TCondition> = {
    [K in keyof T]: T[K] extends TCondition
      ? K
      : never;
  }[keyof T];

type Bar = KeysOfValue<Foo, string>;

但这个方法不适用于嵌套对象。比如对于如下类型:

type Bazz = {
  inner : {
     a : number,
     b : string,
  }
}

如何得到等于"inner.b"的类型?


解决方案:递归提取嵌套属性路径

我们可以用递归条件类型遍历嵌套对象的所有层级,收集符合类型条件的属性路径:

// 辅助类型:判断是否为非null的对象类型
type IsObject<T> = T extends object ? T extends null ? false : true : false;

// 递归提取符合目标类型的属性路径
type NestedKeysOfValue<T, TCondition> = {
  [K in keyof T]: 
    // 当前属性值是目标类型,直接返回键名
    T[K] extends TCondition 
      ? K 
      : // 当前属性是对象,递归处理并拼接路径
        IsObject<T[K]> extends true 
          ? `${K}.${NestedKeysOfValue<T[K], TCondition>}` 
          : never;
}[keyof T];

// 测试嵌套类型
type Bazz = {
  inner : {
     a : number,
     b : string,
     deep: {
       x: boolean,
       y: string
     }
  },
  outer: string
}

// 结果:"outer" | "inner.b" | "inner.deep.y"
type TargetPaths = NestedKeysOfValue<Bazz, string>;

代码说明

  • IsObject:用来区分原始类型和对象类型,避免对非对象类型进行无效递归。
  • NestedKeysOfValue:
    1. 遍历对象的每个键K,检查对应值的类型:
      • 如果值符合目标类型TCondition,直接返回当前键K;
      • 如果值是对象类型,就递归处理这个嵌套对象,并用模板字符串把当前键和子路径拼接起来;
      • 其他情况返回never,最终会被联合类型自动过滤。
    2. 最后通过[keyof T]提取所有有效路径,形成包含所有层级符合条件的路径联合类型。

这样就能得到所有嵌套层级中值为目标类型的属性路径,比如示例中的Bazz类型会返回"outer" | "inner.b" | "inner.deep.y"。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 17:54:54