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

TypeScript中如何无冗余实现动态更新对象嵌套值?

最优实现方案

我们可以通过统一维护运行时映射与类型推导的方式,彻底消除重复代码,同时保持函数签名不变,且无需额外类型转换。核心思路是让类型系统自动从运行时的配置映射中推导所需类型,避免手动维护重复的类型定义与校验逻辑。

完整实现代码

// 运行时维护的分类-键映射,这是唯一需要手动修改的地方
const categoryKeyMap = {
  categoryOne: ['a', 'b', 'c'] as const,
  categoryTwo: ['x', 'y', 'z'] as const
} as const;

// 从映射自动推导合法的分类类型
type ValidCategory = keyof typeof categoryKeyMap;

// 从映射自动推导IFoo类型,无需手动维护每个分类的嵌套结构
type IFoo = {
  [Category in ValidCategory]: {
    [Key in typeof categoryKeyMap[Category][number]]: string;
  };
};

// 初始化对象,类型自动匹配IFoo
const obj: IFoo = {
  categoryOne: {
    a: 'a_string',
    b: 'b_string',
    c: 'c_string',
  },
  categoryTwo: {
    x: 'x_string',
    y: 'y_string',
    z: 'z_string',
  }
};

// 通用校验函数:验证分类和键的合法性,并返回收窄后的类型
function getValidatedCategoryKey(
  category: string,
  key: string
): { category: ValidCategory; key: typeof categoryKeyMap[ValidCategory][number] } | null {
  // 校验分类是否合法
  if (!(category in categoryKeyMap)) return null;
  const validCategory = category as ValidCategory;
  
  // 校验当前分类下的键是否合法
  const validKeys = categoryKeyMap[validCategory];
  if (!validKeys.includes(key as typeof validKeys[number])) return null;
  
  return {
    category: validCategory,
    key: key as typeof validKeys[number]
  };
}

// 保持原函数签名不变的更新函数
function changeObj(category: string, key: string, value: string, obj: IFoo): void {
  const validated = getValidatedCategoryKey(category, key);
  if (!validated) return;
  
  // TypeScript可自动推断obj[validated.category][validated.key]的类型为string,无类型错误
  obj[validated.category][validated.key] = value;
}

// 调用示例
changeObj('categoryOne', 'b', 'B_STRING', obj);

方案优势

  1. 极低维护成本:新增分类时,仅需在categoryKeyMap中添加一行键数组即可,类型定义、校验逻辑、对象结构都会自动适配,无需修改其他代码。
  2. 类型安全无转换:通过类型推导和类型守卫,TypeScript能自动识别合法的分类与键组合,避免了any类型或强制类型转换的使用。
  3. 逻辑复用:校验逻辑被封装为通用函数,无需为每个分类编写重复的类型守卫或switch分支。
  4. 保持原函数签名:完全满足“category和key必须为string类型”的要求,适配HTML表单输入的场景。

新增分类示例

如果需要新增categoryThree,只需修改categoryKeyMap和初始化对象:

// 更新映射
const categoryKeyMap = {
  categoryOne: ['a', 'b', 'c'] as const,
  categoryTwo: ['x', 'y', 'z'] as const,
  categoryThree: ['p', 'q', 'r'] as const // 新增分类
} as const;

// 更新初始化对象
const obj: IFoo = {
  // ... 原有分类
  categoryThree: {
    p: 'p_string',
    q: 'q_string',
    r: 'r_string',
  }
};

此时changeObj函数无需任何修改,即可安全处理categoryThree的键更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 14:45:46