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

TypeScript实现对象泛型属性分离及类型报错解决

需求说明

实现对象拆分功能:从单个大对象中拆分生成两个对象,按属性是否属于指定泛型类型的定义范围做区分。

示例源对象:

{
   name: "John",
   enabled: false,
   lastName: "Doe",
   age: 33
}

指定泛型类型定义:

type User = {
   name: string;
   lastName: string;
   age: number 
}

函数预期返回元组格式为[不属于该类型的属性对象, 属于该类型的属性对象],对应上述示例的预期返回结果:

[
   {
      enabled: false
   }, 
   {
      name: "John",
      lastName: "Doe",
      age: 33
   }
]
原有实现问题

原有实现代码如下,运行时触发类型报错:

type GenericType<T> = Partial<T> & {
[record: string]: unknown
}

// Values are known properites of T
const sortProperties = <T>(values: string[], orginalObject: GenericType<T>){

   const validPropertieis: Partial<T> = {};
   const inValidProperties: Record<string, unknown> = {};

   Object.keys(orginalObject).forEach((key) => {
      if(values.includes(key){
         // No index signature with parameter type 'string' was found on type Partial<T>
         validPropertieis[key] = values[key];
      }
      else {
          inValidProperties[key] = values[key];
      }

   return [inValidProperties, validProperties];

}

报错信息:Partial类型上不存在参数类型为'string'的索引签名。

除了类型报错外,原代码还存在几处逻辑笔误:

  • 属性名拼写错误:validPropertieis、orginalObject拼写有误
  • if(values.includes(key)语句缺少闭合右括号
  • 取值逻辑错误:拆分属性时错误从传入的values数组取值,实际应该从源对象上取对应键的值
  • 逻辑错误:return语句写在了forEach循环内部,会导致遍历第一个属性后就直接终止函数
修正后实现

报错核心原因是TypeScript中Object.keys()默认返回string[]类型,无法直接证明遍历出的字符串属于泛型T的合法键,同时Partial<T>类型默认没有开放字符串索引签名,直接用字符串键赋值会触发类型校验。

修正后的完整可运行代码:

// 定义入参对象类型:兼容泛型T的结构,同时支持任意额外自定义属性
type GenericObject<T> = Partial<T> & Record<string, unknown>;

const sortProperties = <T extends object>(
  targetKeys: Array<keyof T>,
  sourceObj: GenericObject<T>
): [Record<string, unknown>, Partial<T>] => {
  const validProperties: Partial<T> = {};
  const invalidProperties: Record<string, unknown> = {};

  Object.keys(sourceObj).forEach((key) => {
    const sourceValue = sourceObj[key];
    if (targetKeys.includes(key as keyof T)) {
      // 临时做类型断言绕开索引签名校验,不破坏最终返回的类型安全
      (validProperties as Record<string, unknown>)[key] = sourceValue;
    } else {
      invalidProperties[key] = sourceValue;
    }
  });

  return [invalidProperties, validProperties];
};

// 用法示例
type User = {
  name: string;
  lastName: string;
  age: number;
};

const sourceData = {
  name: "John",
  enabled: false,
  lastName: "Doe",
  age: 33
};

const [nonUserFields, userFields] = sortProperties<User>(
  ["name", "lastName", "age"],
  sourceData
);

修正点说明:

  • 修复所有原有笔误,调整return位置到遍历结束后,保证所有属性都能被遍历判断
  • 优化入参类型:将属性列表参数从string[]改为Array<keyof T>,从类型层面约束传入的属性名必须是泛型T的合法键,避免传入无效属性名
  • 对赋值时的validProperties做临时类型断言解决索引签名报错,不改变最终返回值的Partial<T>类型定义
  • 明确函数返回值为元组类型,和预期返回结构对齐,调用时可以直接拿到结构正确的两个拆分对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 15:45:39