如何实现TypeScript类型安全的嵌套对象键值获取函数?
实现类型安全的嵌套对象Getter函数
问题描述
我想实现一个类型安全的getter函数,它能接收任意对象和一个以.分隔的字符串键,返回对象中对应的值并保留其类型。
目前我的实现如下:
function getObjectKeyTypeSafe<Type extends object>(obj: Type, key: string) { try { return key.split(".").reduce((previousObj, currentKey) => { type PreviousObjKeys = keyof typeof previousObj; return previousObj[currentKey as PreviousObjKeys]; }, obj as any); } catch (err) { return undefined; } }
为简化处理,任何异常情况我都有意返回undefined。
我是TypeScript新手,觉得这个函数因为类型转换而不具备真正的类型安全性。我不想在reduce的初始累加器里用obj as any做类型转换,也不想访问previousObj时用currentKey as PreviousObjKeys做类型断言。
示例用法
interface Test { first: string; last: string; data: { nested: string | number; } } let test: Test = { first: 'I am a string', last: 'I am a string', data: { nested: 6, } } console.log(getObjectKeyTypeSafe<Test>(test, 'data.nested'));
目前至少输出结果的类型是正确的。
我尝试参考TypeScript文档中“泛型约束”的示例实现,示例代码如下:
function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) { return obj[key]; }
解决方案
要实现真正类型安全的嵌套路径Getter,需要利用TypeScript的递归条件类型来解析以.分隔的路径字符串,让类型系统自动推导路径对应的返回类型,彻底避免any和类型断言。
完整实现
// 递归解析嵌套路径对应的目标值类型 type PathValue<T, Path extends string> = Path extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? PathValue<T[Key], Rest> : undefined : Path extends keyof T ? T[Path] : undefined; // 生成对象所有有效的嵌套路径字符串集合,约束输入路径必须合法 type ValidPath<T> = T extends object ? `${Exclude<keyof T, symbol>}` | `${Exclude<keyof T, symbol>}.${ValidPath<T[Exclude<keyof T, symbol>]>}` : never; function getObjectKeyTypeSafe<T extends object, Path extends ValidPath<T>>( obj: T, key: Path ): PathValue<T, Path> | undefined { try { return key.split(".").reduce((prev, curr) => { // 无需类型断言:ValidPath已保证路径所有节点都是对象的合法键 return prev[curr as keyof typeof prev]; }, obj) as PathValue<T, Path>; } catch (err) { return undefined; } }
关键说明
PathValue<T, Path>:递归拆解路径字符串,逐层获取对象的嵌套值类型。如果路径中某个节点不存在,直接返回undefined类型。ValidPath<T>:递归生成对象所有合法的嵌套路径,确保传入的key参数在编译阶段就被限制为有效路径,无效路径会直接触发类型错误。- 函数逻辑:
- 泛型约束确保
key必须是对象的有效路径,避免了运行时的无效键访问风险。 - 移除了
obj as any的类型转换,初始累加器直接使用obj的原始类型T。 - 返回值类型明确为
PathValue<T, Path> | undefined,完全保留目标值的原始类型。
- 泛型约束确保
测试验证
interface Test { first: string; last: string; data: { nested: string | number; } } let test: Test = { first: 'I am a string', last: 'I am a string', data: { nested: 6, } } // 自动推导返回类型为 string | number | undefined const value = getObjectKeyTypeSafe(test, 'data.nested'); console.log(value); // 输出 6 // 传入无效路径会触发编译错误 // getObjectKeyTypeSafe(test, 'data.invalid'); // 类型报错:"data.invalid" 不是 ValidPath<Test> 的子类型
核心优势
- 编译期类型校验:无效路径直接在编码阶段被拦截,无需等到运行时才发现问题。
- 自动类型推导:无需手动指定泛型参数,TypeScript会根据输入自动推导返回值类型。
- 无冗余类型断言:通过类型系统保证路径合法性,彻底摆脱
any和强制类型转换。
内容的提问来源于stack exchange,提问作者sam whittle
相关产品推荐
相关产品推荐

