关于typescript:TS中-Arrayreduce提示没有与此调用匹配的重载

6次阅读

共计 1356 个字符,预计需要花费 4 分钟才能阅读完成。

起因

一个 feature 开发, 后果需要评审、工时预估, 几乎是事变级别的. 最初, 迫于无奈, 全组人都得下来救火 …

明天, 帮忙改 bug 的时候, 发现新 checkout 下来的代码, 还带着陈腐的语法错误 … 几乎大无语.

翻了遍代码, 发现很多中央都存在 Array.reduce 类型重载相干的问题, 简略记录一下解决过程.

排查过程

大家的 vscode 都不装语法提醒插件么? 代码挂着红线, 就扔代码库了??? 抽时间, 得把 hook 安顿上了🙄

// 业务代码不不便外流, 简略写了个 demo, 问题起因雷同
const nums = [1, 2, 3, 4, 5];

const sum = nums.reduce((pre, cur) => {return [...pre, { count: cur}];
}, []);

sum.push({count: 6});

console.log(sum);

// 这段代码, 编译成.js 后, 其实是能够运行的. 但如果装了插件, 能够看到显著的 TS 语法错误..
// 输入值
// [//   { count: 0},
//   {count: 1},
//   {count: 2},
//   {count: 3},
//   {count: 4},
//   {count: 5},
//   {count: 6}
// ]

(pre, cur)=>{} 会提醒没有对应的重载类型. 起因不简单, 就是类型不合乎推导预期, 但为什么不合乎预期, 还真没认真看过. 本着 fixbug 能够, 但不能满载而归的思维, 查看了对应的 TS 类型申明

// 3 种 reduce 的类型申明
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T;

reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
 
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;

很显著, reduce 对类型的推导, 根本就是,「参数类型」和「返回值类型」雷同、且 reduce 前后, 只有一种类型, 那不必加「泛型」

然而, 如果呈现 1 种以上的类型, 且 preValue 与 initValue、returnType 类型不同 , 就必须显式标注类型.

案例中, pre 的类型为 never[], cur 的类型是 number, 而 reduce 的返回值类型是 Array<{count: number}>. 依据之前推导的论断, 呈现 3 种类型, 且 pre 与 cur、return 值类型不同, 必须显式申明类型.

依据 TS 的类型申明, 有 2 种可用的解决办法:

  1. 给 initValue 减少类型断言, [] as Array<{ count: number}>.
  2. 在 reduce 处, 申明泛型类型 nums.reduce<Array<{count: number}>>

外围解决思路: 缩小 TSC 推导类型的品种, 促使其合乎已存在的类型定义.

吐槽

只有思维不滑坡, 方法总比艰难多

问题很直观, 也不简单. 但看 log, 这语法问题曾经存在 2 个月了, 真的是 vscode 没装插件么?

正文完
 0