为何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:
- 处理
HouseAddress:HouseAddress extends never不成立,返回keyof HouseAddress→"street" | "number" | "city" - 处理
undefined:undefined extends never不成立,返回keyof undefined→never - 最终结果是
"street" | "number" | "city" | never,而never会被联合类型吸收,最终等价于"street" | "number" | "city"
这样${Key}.${What<T[Key]>}就会生成"house.street" | "house.number" | "house.city"这类合法路径,完美匹配需求。
内容的提问来源于stack exchange,提问作者Pumkko
相关产品推荐
相关产品推荐

