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

如何根据传入对象的键扩展对象并实现TypeScript类型推导?

实现动态生成set方法的TypeScript类型化

要解决这个问题,核心是通过TypeScript的模板字面量类型和映射类型,精确描述返回对象的结构,让TypeScript能识别动态生成的setXXX方法。

步骤1:实现运行时的首字母大写函数

首先补全你代码中缺失的ucFirst函数:

function ucFirst(str: string): string {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

步骤2:定义类型工具

通过类型编程生成对应setXXX方法的类型:

// 将键名首字母大写的类型工具
type CapitalizeKey<K extends string> = Capitalize<K>;

// 生成所有set方法的类型映射
type SetMethods<T extends Record<string, any>> = {
  [K in keyof T as `set${CapitalizeKey<K>}`]: (value: T[K]) => void;
};

步骤3:改造getData函数

修改函数的返回类型,将原对象类型与生成的set方法类型合并,并通过类型断言让TypeScript识别动态添加的属性:

const getData = <T extends Record<string, any>>(initState: T): T & SetMethods<T> => {
  // 初始化时复制原状态,同时断言为目标类型
  const temp = { ...initState } as T & SetMethods<T>;

  for (const [key, _] of Object.entries(initState)) {
    // 动态添加set方法,并指定参数类型为对应属性的类型
    temp[`set${ucFirst(key)}` as keyof SetMethods<T>] = (value: T[typeof key]) => {
      // 这里可以实现实际的状态更新逻辑,例如:
      temp[key as keyof T] = value;
    } as SetMethods<T>[keyof SetMethods<T>];
  }

  return temp;
};

测试效果

现在调用getData后,TypeScript会正确识别所有属性和set方法:

const a = getData({ test: 'demo', count: 123 });

// 原属性有类型提示
a.test; // 类型:string
a.count; // 类型:number

// set方法有正确的参数类型提示
a.setTest('new demo'); // 参数必须是string类型
a.setCount(456); // 参数必须是number类型

原代码问题分析

你之前的代码返回的是Record<string, any>,这是一个宽泛的类型,TypeScript无法推断出具体的键和方法信息。通过上述类型工具,我们将返回类型精确为T & SetMethods<T>,既保留了原对象的所有属性类型,又添加了动态生成的set方法类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 12:30:58