起因
一个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种可用的解决办法:
- 给initValue减少类型断言,
[] as Array<{ count: number }>
. - 在reduce处, 申明泛型类型
nums.reduce<Array<{ count: number }>>
外围解决思路: 缩小TSC推导类型的品种, 促使其合乎已存在的类型定义.
吐槽
只有思维不滑坡, 方法总比艰难多
问题很直观, 也不简单. 但看log, 这语法问题曾经存在2个月了, 真的是vscode没装插件么?