TypeScript实战指南
上QQ阅读APP看书,第一时间看更新

前言

与TypeScript相遇,还是在ThoughtWorks工作的时候。那个时候,我们需要维护大量的前端遗留项目,需要与客户规划我们的人效,需要控制系统迭代带来的bug率。我们接手的项目往往缺乏严谨的注释和完整的代码说明文档,这导致在维护JavaScript遗留项目时,需要花费更多的时间去厘清参数及函数之间的关系,甚至需要用debugger逐层去观察值的变化。工作非常低效,但客户的需求又总是急迫的,这迫使我们去思考如何提升团队的工作效率。

这个时期也是Facebook开始推广Flow的时候。我们觉得添加静态类型应该是个非常不错的方向,也看了很多应用静态类型的成功案例。碰巧Flow对于遗留项目非常友好,你不需要为每个文件、每个函数、每行代码都添加类型,而只需要在你认为有必要的地方写上类型即可。所以我们很快进行了实验。

然而,我们在采用Flow后不久就发现了很多新产生的问题:

1)升级困难,配置复杂。尤其是在React Native项目中,经常会在升级后运行失败。

2)生态弱势。很多第三方库当时没有Flow的类型问题件。

3)难于上手。Flow的气质更像考究的学院派风格,功能强大灵活,但对于新加入团队的人而言,其难度令人生畏。

于是,我们又将目光投向了TypeScript。最初了解TypeScript是看到Angular团队在更新Angular 2时开始全面采用TypeScript代码。他们给出了这样两个理由:

1)TypeScript明确了抽象。在大型工程项目中,我们希望模块之间的边界是使用接口定义的,而JavaScript不足以清晰表达类似的边界划分,Flow也不能。而TypeScript可以定义接口,可以强制程序员去思考API的边界,去设计代码,而不只是编写代码,暴露代码的耦合。

2)TypeScript可以使代码在一定程度上达到“Self-documenting”的效果。“Self-documenting”是一个非常有意思的概念,它强调的是代码本身具有自我说明的效果,而不是依赖文档。TypeScript有着非常严格的强类型表达,这迫使你在函数使用之前就必须标注好函数的入参和返回值类型。这样的强依赖使得函数本身表达清晰,同时也可以非常容易地推导出代码的依赖结构,进行重构。

之后,我们开始尝试在遗留项目中进行TypeScript重构,那是一种相见恨晚的感觉。从后期的数据来看,我们很有效地降低了bug率,同时支持项目的人效也得到了极大的提升。

这一段经历,使我重新开始思考关于语言静态类型的问题。在大型团队开发时,沟通的成本往往是极高的。这就是为什么在后端开发中,拥有静态类型的语言仍然占据主流,也是为什么Python在3.5版本中加入Type Hint。显式的类型声明不仅有利于阅读,也有利于代码编辑器进行代码提示和依赖分析。

比如,在Java开发中,如果需要重构的话,依赖IntelliJ IDEA提供的函数重构功能,可以自动地对每一个依赖该函数的文件进行自动化重构。但这在JavaScript中是不可想象的,你只能使用全局文本搜索来修改函数名,这种操作非常原始,就像在现代战争中还拿着石锤向着敌方阵地冲刺一样。

这就是TypeScript为JavaScript生态带来的价值,也是为什么Angular和Vue都转向使用TypeScript进行重构。比起学术型的Flow而言,TypeScript更像一门工程型的语言,它配置容易,上手快速,更适合在实战中使用,是一件非常称手的“兵器”。

我希望读者在使用TypeScript之前,能够对TypeScript有足够的了解。我结合TypeScript的官方手册与其他公开资料,整理了一些TypeScript基础的内容,就是本书的“基础篇”,最好粗略过一遍这部分内容。在“实战篇”中会提及这些内容,返回去再看时,反而能加深理解。

实际上,如何在实战中使用TypeScript反而是一个老大难的问题。这也是初学者更容易遇到的困难。“为什么手册读完了,官方实例也看了,我还是不会在React里写TypeScript呢?”这是我经常听到的反馈,希望本书能够很好地回答这类问题。

最后,非常感谢2018年年底的住院经历,因为无法完全被治愈,使得我开始重新思考生命与健康的问题,如果有机会我也非常想聊聊这个话题。我非常感谢娜娜的陪伴,这是最长情的告白。同时感谢吴怡编辑的理解与体谅,使得我还有机会完成此书。最后感谢开源社区,不仅帮助我成长,也提供了丰富的资料助力我完成此书,希望能有更多的机会回馈社区。

作者

于2019年元宵节