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

不使用大量重载实现Typescript嵌套对象属性路径访问的类型推导

TypeScript嵌套对象路径访问函数无重载实现方案

需求说明

实现嵌套对象属性路径访问函数的类型推导,满足两个核心要求:

  • 支持传入任意层级的属性键,自动返回对应属性值的正确类型
  • 传入非法属性键时直接抛出类型错误
    原有逐层级编写函数重载的方案会出现「重载爆炸」问题,无法适配任意层级的访问需求。

实现代码

首先实现你提到的元组Tail类型,再通过递归类型实现深度取值推导,不需要任何手动重载:

// 元组Tail类型:返回去掉第一个元素后的剩余元组
type Tail<T extends any[]> = T extends [any, ...infer R] ? R : never;

// 深度取值类型:传入对象T和路径元组P,返回最终路径对应的属性类型
type PathValue<T, P extends PropertyKey[]> = 
  P extends [infer K extends PropertyKey, ...infer Rest extends PropertyKey[]]
    ? K extends keyof T
      ? Rest extends [] ? T[K] : PathValue<T[K], Rest>
      : never
    : never;

// 路径访问函数实现
function get<T extends object, P extends PropertyKey[]>(
  obj: T,
  // 约束参数:空路径、非法路径都会被约束为never,触发类型报错
  ...keys: P extends [] ? never : PathValue<T, P> extends never ? never : P
): PathValue<T, P> {
  // 运行时逻辑可根据需求自行实现,此处为简化示例
  return keys.reduce((current, key) => (current as any)[key], obj) as any;
}

测试验证

interface TestObject {
  person: {
    firstName: string;
    lastName: string;
    address: {
      country: string;
      city: string;
      street: string;
    }
  }
  id: string;
}
const t: TestObject = {} as any;

// 合法路径:类型自动推导正确
const result1 = get(t, 'person', 'address');
// result1类型:{ country: string; city: string; street: string; }

const result2 = get(t, 'id');
// result2类型:string

const result3 = get(t, 'person', 'address', 'city');
// result3类型:string

// 非法路径:直接触发类型错误
const error1 = get(t, 'id', ''); 
// 报错:类型“["id", ""]”的参数不能赋给类型“never”的参数。ts(2345)

const error2 = get(t, 'person', 'notExistKey');
// 报错:类型“["person", "notExistKey"]”的参数不能赋给类型“never”的参数。ts(2345)

说明

该实现依赖TypeScript 4.0及以上版本提供的剩余参数泛型推导、可变元组类型、递归条件类型能力,可支持任意层级的属性访问,完全避免了手动编写重载的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 04:06:02