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

带泛型extends约束的reduce函数无法接受合法空对象的问题

TypeScript泛型类型错误:空对象无法赋值给T类型的解决方案

问题代码

转换函数:

const translateConvertedIdentifiers = <T extends BaseQueryResponseRow>(rows: T[]): T[] => {
  return rows.map((row) => {
    const convertedRow = Object.entries(row).reduce<T>((acc, [key, val]) => {
      return { ...acc, [key]: val };
    }, {});

    return convertedRow;
  });
};

基础类型定义:

export type BaseQueryResponseRow = { [column: string]: any };

错误提示

Argument of type '{}' is not assignable to parameter of type 'T'.
  '{}' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'BaseQueryResponseRow'

问题原因

虽然{}符合BaseQueryResponseRow的类型约束,但T是BaseQueryResponseRow的子类型,它可能包含必填属性。比如假设T被实例化为{ id: number; name: string },空对象{}并不具备这些必填属性,因此TypeScript拒绝将其赋值给T类型的参数。

正确解决方案

方案1:简化逻辑(无属性转换需求)

如果你的代码只是复制对象属性(如示例所示),完全不需要使用reduce,直接返回结构复制后的对象即可,类型会自动推导为T:

const translateConvertedIdentifiers = <T extends BaseQueryResponseRow>(rows: T[]): T[] => {
  return rows.map(row => ({ ...row }));
};

方案2:保留reduce逻辑(有属性转换需求)

如果需要在遍历中修改属性值,可将reduce的初始值设为Partial<T>,确保类型兼容,最后因已遍历原对象所有属性,可安全断言为T:

const translateConvertedIdentifiers = <T extends BaseQueryResponseRow>(rows: T[]): T[] => {
  return rows.map((row) => {
    const convertedRow = Object.entries(row).reduce<Partial<T>>((acc, [key, val]) => {
      // 这里添加你的属性转换逻辑
      return { ...acc, [key]: val };
    }, {});

    return convertedRow as T;
  });
};

方案3:调整泛型约束(限制T为索引签名类型)

如果不需要支持带有固定必填属性的T子类型,可将泛型约束改为Record<string, any>,确保T仅为索引签名类型:

const translateConvertedIdentifiers = <T extends Record<string, any>>(rows: T[]): T[] => {
  return rows.map((row) => {
    const convertedRow = Object.entries(row).reduce<T>((acc, [key, val]) => {
      return { ...acc, [key]: val };
    }, {} as T);

    return convertedRow;
  });
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:37:21