目录
- 问题描述
- 尝试的解决办法
- 真正的解决办法
- 结论
一、 问题描述
一个很久没接触的老项目,前两天想看一下里面一个功能,结果前端起不来了。
先上报错:
Error: node_modules/@types/lodash/common/object.d.ts:1026:46 - error TS1005: '?' expected.
1026 : K extends `${infer N extends number}` ? T[N]
~
Error: node_modules/@types/lodash/common/object.d.ts:1026:51 - error TS2536: Type 'N' cannot be used to index type 'T'.
1026 : K extends `${infer N extends number}` ? T[N]
~~~~
Error: node_modules/@types/lodash/common/object.d.ts:1031:46 - error TS1005: '?' expected.
1031 : K extends `${infer N extends number}` ? T[N]
~
Error: node_modules/@types/lodash/common/object.d.ts:1031:51 - error TS2536: Type 'N' cannot be used to index type 'T'.
1031 : K extends `${infer N extends number}` ? T[N]
~~~~
Error: node_modules/@types/lodash/common/object.d.ts:1041:46 - error TS1005: '?' expected.
1041 : K extends `${infer N extends number}`
~
用中文关键词搜了一下,网上有不少类似的问题。
此项目的环境(展示与问题相关的部分):
"dependencies": {
// angular 12
"@angular/common": "~12.1.2",
"@angular/core": "~12.1.2",
// lodash
"lodash": "^4.17.21",
},
"devDependencies": {
// lodash 的 typescript 声明
"@types/lodash": "^4.14.182",
// ts 版本
"typescript": "~4.3.2"
}
二、 尝试的解决办法
本小节列举网络中提到的解决办法:
更新typescript版本
出处: https://blog.csdn.net/m0_69838795/article/details/140886656
出处2: https://www.cnblogs.com/yalong/p/15502222.html
npm install typescript@latest
这种办法的问题在于,历史项目的ts版本是不能动的,一旦ts版本变更就会有更多的组件不满足依赖要求。
例如Angular 12 要求的版本范围比较窄:
Error: The Angular Compiler requires TypeScript >=4.2.3 and <4.4.0 but 4.8.4 was found instead.
修改lodash版本 或 @types/lodash 版本
出处: https://cloud.tencent.com/developer/ask/sof/794816
出处2: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/69932
类似的文章中,有两种说法:
- 更新为特定版本,如 @types/lodash@ts2.1.5
- 保持@types/lodash和lodash大版本一致
实践证明,不行。或者说针对特殊情况下才可以,属于碰运气而没有给出原理。
笔者没有解决。
三、 真正的解决办法
折腾了一天还没进展的时候,笔者直接去npm找包了。
搜索lodash看到了它的本体和对应的@types:
这里插入一个知识点,这个@types是什么?
上链接:
https://www.tslang.cn/docs/handbook/declaration-files/publish...
https://jkchao.github.io/typescript-book-chinese/typings/type...
通俗的说,拿lodash举例,lodash本体是js库,为了在ts中使用,就对这个库编写一个对应的声明文件,以便ts能够比较好的识别这个库。
了解这个原理后,我们继续。
看看lodash的版本,没有什么发现。只找到了版本号和发布时间:
https://www.npmjs.com/package/lodash?activeTab=versions
再来看@types的版本,发现了关键:
https://www.npmjs.com/package/@types/lodash?activeTab=versions
它是有tag的,而tag指明了:@types/lodash的版本和ts版本之间的匹配情况。
因此我们得出一个结论:
- 不是@types/lodash和lodash的版本对应
- 而是@types/lodash和ts的版本对应
回到本文开头说的,我们的ts是4.3.2,因此需要找tag为4.3的版本:
4.14.198可以兼容ts4.3,于是我们安装这个版本:
npm install @types/lodash@4.14.198
装好之后,问题迎刃而解:
四、 结论
最后一小节,来讨论一下为什么好好的项目,同样的依赖文件,前两年能跑,现在什么都没动,为什么就跑不了了呢?
- 我们一般称npm中的版本为
x.y.z
。 - x为大版本,x的变化会导致代码大范围重构
- y为中版本,y的变化会导致一些api变化
- z为小版本,z的变化通常只包含bug修复
来看看@types/lodash的小版本:
原则上,z的变化不应该造成代码的重大改动,而上图中:
- 4.14.198仍然保留着ts4.3的兼容
- 但只有小版本变化的4.14.202却删掉了ts4.3的兼容
而我们的package.json是这么写的:
"@types/lodash": "^4.14.182",
这里再引入一个知识点:
- ^ 表示小版本和中版本可变,大版本不变
- ~ 表示小版本可变,中版本和大版本不可变
那这个写法就有问题了,版本已经漂移到不知道哪里去了。
对于@types/lodash这种小版本变化都会改变兼容性的包,比较稳妥的做法是:
- 锁定小版本
这样基本就解决问题了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。