TypeScript使用reduce设置初始值出现类型报错如何解决?
问题1:为什么TypeScript不认可当前的reduce写法
- 初始值类型推断错误:你传入的初始值是
{ people: [] },TypeScript默认会把无类型标注的空数组推断为never[],因为没有足够上下文判断数组元素的类型,后续往数组里新增对象自然会触发类型不匹配报错。 - 类型重叠度不足:你的
FruitPersonMap要求必须存在apple/banana/pear/plum/grape五个必填的字符串数组成员,而初始值{ people: [] }完全没有这些属性,两种类型没有足够重叠部分,直接用as FruitPersonMap强制转换会触发类型警告。 - 额外潜在问题:你给出的
fruitConsumers第二个子数组长度为6,比fruits的5个元素多,当索引为5时currentFruit会是undefined,会生成非预期的键值。
问题2:正确的解决方案
核心方法是给reduce显式指定泛型参数,明确累加器的类型为FruitPersonMap,同时规范初始值的结构:
你可以选择提前构造包含所有水果空数组的完整初始值,这种写法类型安全性最高,修改后的代码如下:
const makeFruitPersonMap = (fruits: string[], consumers: string[][]): FruitPersonMap[] => { return consumers.map(consumerSet => { // 显式给reduce指定泛型,约束累加器类型为FruitPersonMap return consumerSet.reduce<FruitPersonMap>((acc, val: string, i: number) => { // 避免索引超过fruits长度的边界问题 if (i >= fruits.length) return acc; const currentFruit = fruits[i] as keyof FruitPersonMap; // 分割后过滤空字符串,避免生成名字为空的无效数据 const peopleList = val.split(',').map(name => name.trim()).filter(Boolean); const peopleWithFruit = peopleList.map(person => ({ name: person, fruit: currentFruit, })) return { ...acc, [currentFruit]: peopleList, // 初始值已声明people为数组,直接拼接即可,无需多余判断 people: [...acc.people!, ...peopleWithFruit] } // 初始值完全符合FruitPersonMap的类型要求,不会触发类型警告 }, { apple: [], banana: [], pear: [], plum: [], grape: [], people: [] }) }) };
如果你不想手动枚举所有水果的初始空数组,也可以先把FruitPersonMap里的水果属性改为可选,或者借助as unknown as FruitPersonMap的二级断言辅助,但手动声明初始值的可维护性和类型安全性最优。另外代码里acc.people!的非空断言是安全的,因为初始值已经明确传入了people: [],不会出现undefined的情况。
内容的提问来源于stack exchange,提问作者JSilv
相关产品推荐
相关产品推荐

