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

TypeScript编写访问嵌套对象键的函数时无法访问属性问题

嵌套对象属性访问的TS类型报错修复

问题场景

需要实现一个接收key和subKey两个参数的函数,用来访问嵌套存储对象的对应属性,已经完成了基础类型定义,但函数内部无法正常访问目标对象的myFunction、someData属性。

问题复现代码

type ObjectDefinationType<T> = {
  myFunction: () => void;
  data?: T[];
  someData: string;
};

type KeySet1 = "key1" | "key2";
type KeySet2 = "key3" | "key4";

type DataType1 = {
  id: string;
  num: number;
};

type DataType2 = {
  age: number;
  address: string;
};

type KeySet1Record = Record<KeySet1, ObjectDefinationType<DataType1>>;
type KeySet2Record = Record<KeySet2, ObjectDefinationType<DataType2>>;

type SetStoreType = {
  set1: KeySet1Record;
  set2: KeySet2Record;
};

const initialData = {
  myFunction: () => {},
  someData: "someData"
};
const set1: KeySet1Record = {
  key1: { ...initialData },
  key2: { ...initialData }
};
const set2: KeySet2Record = {
  key3: { ...initialData },
  key4: { ...initialData }
};

const setStore: SetStoreType = {
  set1,
  set2
};

const myFunc = <T extends keyof SetStoreType, K extends keyof SetStoreType[T]>(
  key: T,
  subKey: K
) => {
  // 此处访问属性报类型错误
  console.log("I want to access data", setStore[key][subKey].someData);

  // 此处赋值报类型错误
  setStore[key][subKey].myFunction = () => {
    // 函数逻辑
  };
};

报错原因

TS对多层嵌套的泛型索引存在类型收敛缺陷:当使用两层泛型参数分别约束外层key和内层subKey时,TS无法正确关联两个泛型参数的对应关系,会把setStore[key][subKey]的类型推断为不具备已知属性的交叉类型,导致无法正常访问上面定义的myFunction、someData属性。

修复方案

不需要修改原有类型定义,也不需要用全量覆盖对象的绕路写法,两种可直接落地的方案如下:

  • 方案1:取出嵌套值后通过类型断言明确类型
const myFunc = <T extends keyof SetStoreType, K extends keyof SetStoreType[T]>(
  key: T,
  subKey: K
) => {
  // 明确嵌套值的类型
  const target = setStore[key][subKey] as ObjectDefinationType<DataType1 | DataType2>;
  
  // 正常访问属性
  console.log("I want to access data", target.someData);

  // 正常赋值方法
  target.myFunction = () => {
    // 函数逻辑
  };
};
  • 方案2:优化泛型索引的类型声明,让TS自动收敛类型
const myFunc = <T extends keyof SetStoreType, K extends keyof SetStoreType[T]>(
  key: T,
  subKey: K
) => {
  const store = setStore as Record<T, Record<K, ObjectDefinationType<any>>>;
  const target = store[key][subKey];
  
  console.log("I want to access data", target.someData);
  target.myFunction = () => {
    // 函数逻辑
  };
};

两种写法都可以让属性访问和赋值的类型检查正常通过,运行时逻辑和预期完全一致。


内容的提问来源于stack exchange,提问作者Kunal Jain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:03:24