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

为何What类型可解决NestedPath的Symbol键赋值兼容问题?

为什么What类型能解决可选嵌套对象的路径类型问题?

我们要实现一个TypeScript类型Path<T>,用来约束对象的嵌套路径字符串,比如对于以下接口:

interface HouseAddress {
  street: string;
  number: number;
  city: string;
}

interface Person {
  name: string;
  age: number;
  house?: HouseAddress;
  child: Person;
}

要求Path<Person>允许"name"、"house.street"这类合法路径,拒绝"cat.name"这种不存在的路径。

最终实现的核心代码如下:

type What<T> = T extends never ? never : keyof T;

type NestedPath<T, Key extends keyof T> = Key extends string
  ? T[Key] extends Record<string, any> | undefined
    ? `${Key}.${What<T[Key]>}` 
    | `${Key}.${NestedPath<T[Key], keyof T[Key]>}`
    : never
  : never;

// 完整Path类型需补充顶层key
type Path<T> = keyof T extends string ? keyof T | NestedPath<T, keyof T> : never;

核心问题:为什么What可行,另外两种方式不行?

可选字段的类型特性

以Person['house']为例,它的类型是HouseAddress | undefined(因为是可选属性)。TypeScript规定:联合类型的keyof等于各成员keyof的交集。

  • keyof HouseAddress是"street" | "number" | "city"
  • keyof undefined是never(undefined没有可枚举属性)
  • 因此keyof (HouseAddress | undefined) = "street" | "number" | "city" & never = never

两种替代方案的问题

如果直接用Exclude<keyof T[Key], symbol>或者keyof T[Key] & string:

  • 当T[Key]是HouseAddress | undefined时,keyof T[Key]已经是never,两种处理后结果还是never
  • 最终生成的路径会变成"house.never"这类无效类型,无法匹配"house.city"这类合法路径

What的关键:条件类型的分布式特性

What<T>的定义T extends never ? never : keyof T利用了TypeScript条件类型对联合类型的分布式处理:当T是联合类型时,会将每个成员单独代入条件判断,再将结果重新联合。

对于T = HouseAddress | undefined:

  1. 处理HouseAddress:HouseAddress extends never不成立,返回keyof HouseAddress → "street" | "number" | "city"
  2. 处理undefined:undefined extends never不成立,返回keyof undefined → never
  3. 最终结果是"street" | "number" | "city" | never,而never会被联合类型吸收,最终等价于"street" | "number" | "city"

这样${Key}.${What<T[Key]>}就会生成"house.street" | "house.number" | "house.city"这类合法路径,完美匹配需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 21:30:11