TypeScript中如何使用reduce()按值合并对象数组?
解决TypeScript中reduce分组对象的问题
你的问题核心是类型不匹配加逻辑方向错误,咱们一步步梳理清楚:
错误原因分析
- 类型注解与实际返回值不匹配:你给
reduce标注的类型<{ [index: number]: any }>声明最终要返回一个对象,但初始值用了[](数组),且回调函数里返回的也是数组[...res, {...}]。这直接导致TypeScript报错——普通对象没有Symbol.iterator(只有数组、字符串这类可迭代对象才有),所以...res展开对象时触发了2488错误。 - 分组逻辑偏差:你想要的是把同
buildingId的对象合并到同一个数组中,最终应该得到{ [buildingId: number]: 对应对象数组 }的结构,而非把每个分组对象塞进大数组里。
修正后的代码
// 假设sections的类型为 Array<{ buildingId: number; /* 其他属性 */ }> const groupedByBuildingId = sections.reduce<Record<number, typeof sections[0][]>>( (res, section) => { // 获取当前buildingId对应的数组,无则初始化空数组 const existingSections = res[section.buildingId] || []; // 更新对象,将当前section加入对应数组 res[section.buildingId] = [...existingSections, section]; // 返回更新后的对象,而非数组 return res; }, {} // 初始值改为空对象,匹配类型注解要求 );
关键修正点
- 初始值替换为
{}:因为我们要构建的是键值对对象,不是数组。 - 回调内直接操作对象属性:无需生成新数组,直接对
res的buildingId属性做数组拼接。 - 更精确的类型定义:用
Record<number, typeof sections[0][]>替代any,让类型更安全——Record<K, V>表示键为K类型、值为V类型的对象,这里值就是sections元素组成的数组。
补充说明
你之前误解了报错的指向:报错说的是{ [index: number]: any }这个对象类型没有迭代器,和number本身无关。只有数组、字符串、Map、Set这类实现了Symbol.iterator接口的对象,才能用...展开到数组中,普通键值对对象不支持这种操作。
内容的提问来源于stack exchange,提问作者pcace
相关产品推荐
相关产品推荐

