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

如何用TypeScript的Array.reduce实现对象数组按ID去重并累加数量

报错原因
  • reduce泛型参数错误:你声明的reduce返回值类型是MiniBagItem单个对象,但实际初始值是数组、返回值也是数组,类型不匹配直接触发类型报错。
  • Map未指定泛型:TS会默认推断Map的键值为unknown类型,读取obj.sku作为键、获取对应值的时候都会报类型不匹配。
  • 重复插入逻辑:你在三元判断里已经给不存在的条目执行了acc.push(obj),后面又多写了一次acc.push(obj),会导致所有条目重复插入结果数组。
  • 索引逻辑错误:你存到Map里的是原数组的下标,但是结果数组acc的长度和原数组不一样,用原数组下标取acc[seen]根本拿不到正确的对象。
正确实现

基础版(易读)

直接在reduce的累加数组中查找同sku的条目,累加数量即可:

export interface MiniBagItem {
  name?: string;
  sku?: string;
  quantity?: number;
}

const item1: MiniBagItem = { name: "test", sku: "123", quantity: 1 };
const item2: MiniBagItem = { name: "test", sku: "123", quantity: 1 };
const item3: MiniBagItem = { name: "testNew", sku: "456", quantity: 1 };
const miniBagItems: MiniBagItem[] = [item1, item2, item3];

const mergedItems = miniBagItems.reduce<MiniBagItem[]>((acc, current) => {
  // 过滤sku为空的异常数据
  if (!current.sku) return acc;
  // 查找是否已经有同sku的条目
  const existed = acc.find(item => item.sku === current.sku);
  if (existed) {
    // 累加数量,加空值兼容避免TS报错
    existed.quantity = (existed.quantity ?? 0) + (current.quantity ?? 0);
  } else {
    // 新增条目,解构避免修改原对象
    acc.push({...current});
  }
  return acc;
}, []);

高性能版(大数组适用)

结合Map减少每次遍历查找的开销,时间复杂度O(n):

const mergedItems = Array.from(
  miniBagItems.reduce<Map<string, MiniBagItem>>((map, current) => {
    if (!current.sku) return map;
    if (map.has(current.sku)) {
      const existed = map.get(current.sku)!;
      existed.quantity = (existed.quantity ?? 0) + (current.quantity ?? 0);
    } else {
      map.set(current.sku, {...current});
    }
    return map;
  }, new Map())
).map(([, item]) => item);

如果需要按itemId归并,只需要把代码中所有的sku替换为itemId即可,逻辑完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:15:00