TypeScript 给 js 提供了类型系统。它带来了不少优点。

典型的是

  • 为IDE提供了类型注解,可以更好的做检查甚至提前编译检验
  • 更先进的语法支持,提前使用更方便的语法特性,不用担心运行环境的兼容性问题
  • 语法一致性。比如可以一直使用 import/export 系统,会自动处理针对运行环境的适配代码
  • 更为严谨的编程实践。特别是模块间的接口,经过类型定义处理会提升可靠性,错误能很快发现

但是 TypeScript 也带来了使用上的问题,既然需要编译,就一定会有各种编译错误产生。

在Node技术栈项目中引入TypeScript,并不是你想的,仅仅只多了一个编译过程那么简单,它往往把系统复杂度提升了很多。TypeScript 需要配置,配置影响编译结果。而且,第三方库可能并未准备好对 TypeScript 的兼容。

TypeScript

有些编译错误纯粹是语法写错,但是有些错误是比较“诡异”的,让人摸不着头脑,也并不是简单的修改代码就能解决。这里讨论这些问题,并给出解决的办法。

故障1 – 跨主机编译失败:项目在A主机上编译成功,在B主机上编译错误。查看所有的代码版本,环境配置,包括 package.json 完全一致。

可能的原因:没有使用 package-lock.json 文件锁定版本,导致A/B主机上,安装的包版本并不一致,从而导致编译错误。npm 包管理是有缓存的,这个缓存会影响安装效果。比如,A 主机经常更新包,它的缓存可能就比较新。B 主机更新的慢,缓存的包版本就比较旧。在安装的时候,因为 npm 只要版本语义符合就安装,所以从缓存中提取的包各自并不相同。

此外,要格外关注一下 @babel/core 和附属的几个 @babel/xxxx 包的版本差异。实践表明,它们的小版本差别也可能产生编译支持的差异。可以尽量使用更新的版本,增强对新型语法的支持度。

但是,使用 package-lock.json 是有额外的麻烦的。更何况,它的语义和管理模式,在前面的 npm 系统中更改了3次。从而导致一些开发者不喜欢让这个文件进入代码库。还有就是,多人协作开发的时候,会测试安装一些库。反复操作之后,团队成员提交的 package-lock.json 非常容易冲突,让人烦恼。后面 npm 的包管理逐步完善的情况下,还是建议把这个 package-lock.json 文件签入代码库。团队成员要在更新库的时候,进行内部通告,协调一致。在需要部署的主机上,需要使用 “npm ci ”命令安装,确保版本一致性。

如果需要了解 package-lock.json 的设定,可以参考相关的文档资料。

故障2 – 某些类库的使用方式无法编译通过: 比如 ioredis,使用的时候产生编译错误。这个可能的原因是没有安装此库对应的类型系统。或者更新了类库的新版本,没有更新对应的类型系统。如果要正常使用第三方库,通常要一起安装:@types/xxxx 。比如 @types/ioredis 。但是,这个@types/xxx 版本与它追踪的库,往往并没有什么一致性。实际版本号可能差别很大,具体的支持版本,要看文档说明。

有一些库本身是 TypeScript 开发的,甚至在文档中说明,已经对 TypeScript 兼容。但是要注意,你看到的文档,指向的版本可能跟你安装的版本并不一致。你安装使用的版本可能还没有兼容,还是需要类型文件。

故障3 – 不同主机安装的 TypeScript 版本有差异,编译失败。曾经遇到一个问题,package.json 中约定要使用 TypeScript 4.6.3。而且测试中,主机 A 安装的是 TypeScript 4.6.3,但是主机 B 安装就一定会装上 4.8 版本。而 TypeScript 不同版本之间,编译也有兼容性问题,从而产生错误。刚开始以为是缓存问题,使用 “npm cache clean –force”处理也没有效果。

经过调查,原因是主机 B 在 npm install 时候,会下载很多的库。其中某个库提升了一个小版本,而这个小版本,恰好要求依赖 TypeScript 4.6.4 。于是 npm 检查发现后,没有安装4.6.4版本,就直接安装了最新的 TypeScript。这个行为直接导致编译错误。

解决办法是修改提升 package.json 中的 TypeScript 版本到 4.6.4。或者使用 package-lock.json 锁定安装版本环境。

这个软件互相影响,产生的兼容性问题还是很多的。引入的实体越多,系统就越复杂。请记住,TypeScript 并不是银弹,要合理使用,不要滥用。

此外,Node 的版本也有影响。跨版本的编译结果有时候差别巨大。目前生产环境还是惯常使用 Node 的LTS 版本。V14、V16 都是不错的。但是 Node 17以上,一些库编译错误,产生了兼容性问题。这个是因为,这些库在开发的时候,环境就是较为成熟的 Node 版本,而新版本 Node 推出后,它没有同步测试更新。这很常见,因为维护有成本,可能开发者解决了自己的问题就不管了。所以 Node 环境除非必须,不要贪图最新。最新版的配套资源往往还没跟上,容易产生很多意外情况。

为什么我开始劝人远离中国的金融市场?
人口问题的一点思考