惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
WordPress大学
WordPress大学
小众软件
小众软件
云风的 BLOG
云风的 BLOG
IT之家
IT之家
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
博客园 - 【当耐特】
T
Tailwind CSS Blog
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
宝玉的分享
宝玉的分享
博客园 - Franky
F
Fortinet All Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
GbyAI
GbyAI
Hugging Face - Blog
Hugging Face - Blog
Jina AI
Jina AI
D
Docker
博客园 - 聂微东
C
Check Point Blog
H
Help Net Security

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派
TS中, Array.reduce提示没有与此调用匹配的重载? - 少数派
2023-06-16 · via 少数派

起因

一个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没装插件么?