3

目录

  1. 问题描述
  2. 尝试的解决办法
  3. 真正的解决办法
  4. 结论

一、 问题描述

一个很久没接触的老项目,前两天想看一下里面一个功能,结果前端起不来了。

先上报错:

image.png


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

类似的文章中,有两种说法:

  1. 更新为特定版本,如 @types/lodash@ts2.1.5
  2. 保持@types/lodash和lodash大版本一致

实践证明,不行。或者说针对特殊情况下才可以,属于碰运气而没有给出原理。

笔者没有解决。

三、 真正的解决办法

折腾了一天还没进展的时候,笔者直接去npm找包了。

搜索lodash看到了它的本体和对应的@types:

image.png

这里插入一个知识点,这个@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的版本,没有什么发现。只找到了版本号和发布时间:

image.png

https://www.npmjs.com/package/lodash?activeTab=versions

再来看@types的版本,发现了关键:

image.png

https://www.npmjs.com/package/@types/lodash?activeTab=versions

它是有tag的,而tag指明了:@types/lodash的版本和ts版本之间的匹配情况。

因此我们得出一个结论:

  • 不是@types/lodashlodash的版本对应
  • 而是@types/lodashts的版本对应

回到本文开头说的,我们的ts是4.3.2,因此需要找tag为4.3的版本:

image.png

4.14.198可以兼容ts4.3,于是我们安装这个版本:

npm install @types/lodash@4.14.198

装好之后,问题迎刃而解:

image.png

四、 结论

最后一小节,来讨论一下为什么好好的项目,同样的依赖文件,前两年能跑,现在什么都没动,为什么就跑不了了呢?

  • 我们一般称npm中的版本为x.y.z
  • x为大版本,x的变化会导致代码大范围重构
  • y为中版本,y的变化会导致一些api变化
  • z为小版本,z的变化通常只包含bug修复

来看看@types/lodash的小版本:

image.png

原则上,z的变化不应该造成代码的重大改动,而上图中:

  • 4.14.198仍然保留着ts4.3的兼容
  • 但只有小版本变化的4.14.202却删掉了ts4.3的兼容

而我们的package.json是这么写的:

 "@types/lodash": "^4.14.182",

这里再引入一个知识点:

  • ^ 表示小版本和中版本可变,大版本不变
  • ~ 表示小版本可变,中版本和大版本不可变

那这个写法就有问题了,版本已经漂移到不知道哪里去了。

对于@types/lodash这种小版本变化都会改变兼容性的包,比较稳妥的做法是:

  • 锁定小版本

这样基本就解决问题了。


LYX6666
1.6k 声望73 粉丝

一个正在茁壮成长的零基础小白