TypeScript深度嵌套keyof类型报错问题求助
解决TypeScript深度嵌套keyof类型的递归错误
你的问题出在递归类型的终止条件和联合类型的模板字面量拼接逻辑上。原代码在处理多级嵌套对象时会生成无效的字符串字面量,同时未正确过滤非递归类型分支,导致TypeScript报错。
原代码核心问题分析
type DeepKeyof<T> = T extends object ? keyof T | `${keyof T}.${DeepKeyof<T[keyof T]>}` : never;
- 当
T[keyof T]是联合类型(比如同时包含基本类型和对象类型)时,DeepKeyof会对联合类型的每一项分发处理。对于基本类型,DeepKeyof返回never,此时${keyof T}.${never}会生成类似"key."这种以点结尾的无效字符串字面量,触发语法错误。 - 未排除
null和undefined(它们的typeof结果为object,会被错误纳入递归流程)。
修正方案
通过添加严格的类型守卫和映射类型过滤,确保只对有效对象进行递归,同时自动排除无效的拼接结果:
// 定义所有不需要递归的基本类型 type Primitive = string | number | boolean | symbol | null | undefined; type DeepKeyof<T> = // 基本类型直接终止递归,返回never T extends Primitive ? never : // 要么是当前对象的key,要么是递归拼接的嵌套key keyof T | { [K in keyof T]: `${K & string}.${DeepKeyof<T[K]>}` }[keyof T]; // 测试用例 interface Test { a: string; b: { c: number; d: { e: boolean; } } } type Keys = DeepKeyof<Test>; // 正确生成:"a" | "b" | "b.c" | "b.d" | "b.d.e"
修正点说明
- Primitive类型约束:明确排除所有基本类型和空值,避免对非对象类型进行无效递归。
- 映射类型替代直接拼接:通过
{ [K in keyof T]: ... }[keyof T]遍历每个属性单独处理嵌套拼接,自动过滤掉never结果(当属性为基本类型时,对应的拼接项会被排除)。 - K & string:确保key可以被转换为字符串字面量(
keyof T可能包含symbol类型,无法直接用于模板字面量)。
修改后,递归生成的所有嵌套key都是有效的字符串,同时能正确覆盖所有层级的嵌套属性。
内容的提问来源于stack exchange,提问作者Kerschbaumer Stefan
相关产品推荐
相关产品推荐

