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

如何实现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> 的子类型

核心优势

  1. 编译期类型校验:无效路径直接在编码阶段被拦截,无需等到运行时才发现问题。
  2. 自动类型推导:无需手动指定泛型参数,TypeScript会根据输入自动推导返回值类型。
  3. 无冗余类型断言:通过类型系统保证路径合法性,彻底摆脱any和强制类型转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:44:53