vlambda博客
学习文章列表

腾讯IMWEB团队《未来可期的TypeScript》



IMWeb 团队隶属腾讯公司,是国内最专业的前端团队之一。专注前端领域多年,负责过 QQ 资料、QQ 注册、QQ 群等亿级业务。目前聚焦于在线教育领域,精心打磨 腾讯课堂、企鹅辅导及ABCmouse三大产品。


讲述了自己从一名 TypeScript 抵制者转变为支持者的心路历程,以及 TypeScript 在在线教育团队中的实践经验,并对团队新项目是否该引入 TypeScript、如何快速搭建、以及现有项目如何向 TypeScript 迁移提供策略性建议与方案。

开场


2019年,越来越多的知名前端开源项目选择使用 TypeScript 做为其新版本的开发语言,TypeScript 的社区支持也日趋完善,VS Code + TypeScript 的组合拳让不少原本持怀疑,甚至抵制态度的前端开发者们不禁喊出“真香!”。


然而,无论是在大公司还是中小型公司中,依旧有相当多的前端工程师对TS有着理解偏差。TS的官方文档也过于技术性,并没有对TS的诞生原因,所要解决的问题等做细致的解释。所以本次演讲并不会关注太多TS本身的语法,高级用法这类话题,因为在这些方面,官方文档是更好的资料来源。而希望听众在分享结束后,能更明白TS成功的背后,究竟是解决了哪些问题?它的核心是什么?它的与众不同之处在哪?团队是否该引入TS以及如何引入?

腾讯IMWEB团队《未来可期的TypeScript》
Part 1 如何定义TypeScript


1.1 官方定义


腾讯IMWEB团队《未来可期的TypeScript》

TS官网下的定义为“JavaScript that scales”,这句话如果翻译为中文不是一件简单的事。Scales意味着“规模扩大”。而对应的中文官网直接翻译成“JavaScript的超集",显然是有点文不对题的。


然而,这却恰好从两个不同的层面解释了什么是TypeScript。


英文版告诉你,TS与JS的能力区分在哪:即TS更能适应项目规模不断扩大的场景。


中文版告诉你,TS的本质是什么:即它是一种具有类型系统的JS的超集。


1.2 不仅仅是一门语言


腾讯IMWEB团队《未来可期的TypeScript》


如果你觉得定义本身比较空洞,想要更简单直接的了解TS是什么,不如看看它带来了什么。


作为一门语言本身来说,首先带来的是类型安全,可以类比java,c++。


另外,TS包含一个编译器,通过来你可以使用最新最稳定的JS特性,功能类似babel。


最后,最核心的部分,由于ts带来类型,所以你的工具,IDE可以更容易的理解你的代码。从而可以创造很多工具,来帮助你更高效的写高质量的代码。


所以总结起来TS不仅仅是一门语言,而是生产力工具。


腾讯IMWEB团队《未来可期的TypeScript》
3
Part 2 JS世界的傲慢与偏见


说到TS,就不得不提JS,JS作为一门非常有争议的语言,发展到今天成为当下最流行的语言的过程是非常戏剧性的。


有很多必然,也有很多偶然。前端社区有关js的争论,也一天没有消停过,那我们就来看一下js的世界里有哪些有趣的话题。


2.1 开发者的偏见


腾讯IMWEB团队《未来可期的TypeScript》


在过去,很多人把JS当做是一个玩具语言。我们也会发现在某些场景,使用JS的人员并不一定是开发者(譬如早期qq空间通过脚本装饰页面)。更可以毫不夸张的说,很多开发者觉得,JS是一门,等真正需要用到的时候,再去随意学学,就能上手的语言。种种原因导致了JS在很多时候被滥用。


2.1.1 偏见的背后


腾讯IMWEB团队《未来可期的TypeScript》


当然JS本身的确是存在非常多的问题,尤其在早期的时候。没有模块、class、类型。还有一堆为人所诟病的语言设计,null、undefined、NaN等等。


2.1.2 开发者是如何应对JS的种种问题的


腾讯IMWEB团队《未来可期的TypeScript》


虽然JS有诸多糟粕,但是在浏览器里,你没办法摆脱他。“聪明”的开发者们想出了“用我喜欢的语言来编译生成JS”这样的点子,把JS仅仅当作媒介语言。你几乎可以找到任何语言的版本,这其中有像Google的GWT,微软的Script#都是被大规模在正式环境中应用的产品。


慢慢的,一些“更聪明”的开发者觉得这种方式有点不伦不类,不如彻底一点,干脆发明一些新的语言来取代JS。这里面最为出名的就是Google的Dart与CoffeeScript。


2.1.3 取代的结果如何


腾讯IMWEB团队《未来可期的TypeScript》


在google trend中,如果把CoffeeScript、Dart、TypeScript一起搜索。可以看到,从2014年至今,CoffeeScript与Dart基本没掀起任何波浪,而TS迎头直上。


2.1.4 从失败中吸取教训


腾讯IMWEB团队《未来可期的TypeScript》


为什么TS可以,而其他这些语言却没法成为主流呢?这其中主要有三个原因:


1. 没有严格遵从ECMAScript的规范。语法层面他们和JS是完全割裂的。譬如CoffeeScript用的是接近于ruby的语法,当使用这样的语言的时候,你会感觉你是完全在学一门新语言。有一定的学习成本。在ECMAScript规范不断演进的情形下,这类语言的语法就会越来越成为累赘。


2. 性能问题。这在早期的时候更为明显。图中的一段Dart代码,在用Dart的编译器转化为JS后,不做任何优化的情况下,居然产生了10000多行代码。这显然是难以接受的。


3. 生成代码的可读性差,没有办法回退。毕竟只是把JS做为媒介语言,JS的可读性不是这类语言的考量。这也意味着一旦项目启动,就没法很轻松的回退回原生JS。


2.2 来自开发者的傲慢


2.2.1 坊间流言


腾讯IMWEB团队《未来可期的TypeScript》


基于种种原因,开发者们越来越倾向于写原生JS。HTML5,Nodejs,还有像Angular,React,Vue这样优秀的前端框架又把JS的使用推向另一个高度。每一个JS开发者都无比的振奋。于是,渐渐的,我们又听到了另外一种声音。


1. 凡是可以用JS来写的应用,最终都会用JS来写--At Woods定律。


2. js是最好的语言,反正你们饶了一圈最后都会回来。


3. 微软出的东西,能行么?


2.2.2 被微软狠狠打脸


腾讯IMWEB团队《未来可期的TypeScript》


目前在github上热度前十的项目中,微软直接占了两席。而排在第八位的,也是社区中TS的周边产物。


腾讯IMWEB团队《未来可期的TypeScript》


StackOverFlow的报告,在程序员最喜欢的语言中,TS与Python目前并列第二,仅次于Rust。


腾讯IMWEB团队《未来可期的TypeScript》


Npm包的开发者中,高达62%的开发者在使用TS。


从这些数字中可以很明显的看出,当下TS已经取得了相当惊人的成就。


2.2.3 为何TS会取得如此成功


腾讯IMWEB团队《未来可期的TypeScript》


TS会取得如此成功主要有5个原因:


1. 对类型安全的诉求。无论在浏览器还是服务端,前端项目规模越来越大,越来越复杂。而规模越大,对静态类型语言的诉求就越强烈。


2. 严格遵守ECMAScript规范。与那些把JS当作媒介语言的语言是不同的。TS选择改进了JS,而不是取代它。学习ts语法并不会增加额外成本。


3. 采用Structural Typing而不是Nominal Typing。面向对象的语言,一般使用nominal typing(C++, Java, Swift),而函数式语言更习惯使用Structural Typing(OCaml, Haskell, Elm)。JS里面,你即可以使用面向对象,又可以使用函数式。但js的开发者通常更倾向于使用函数式编程。这种情况下,TS选择了使用结构类型,也更符合js开发者的编程习惯。


4. 强大的开发工具。正如我前面提到的,通过工具提高生产力才是TS的核心目标。TS本身提供了非常棒的工具支持,他的TS Server机制是非常有创造性的(后面会详述)。


5. Open Source, Open Development。TS是以100%的开放开发的方式来运营的。也就是说有关与ts的一切,都是对开发者100%透明的。在过去,当你给一门语言提一个bug的之后,可能等一两年才会出新版本,而到那个时候你才会发现,你提的bug可能根本没被修复。通过TS的roadmap你可以清晰的看到具体哪些bug会被修复,哪些feature会被新增,以及所有关于这些技术点的讨论。这样拉近了核心开发团队与使用者的距离,让TS的社区非常的活跃。


腾讯IMWEB团队《未来可期的TypeScript》
4
Part3 腾讯在线教育选择TS的四个理由


3.1 理由一:更少的Bug


3.1.1 研究与实践


腾讯IMWEB团队《未来可期的TypeScript》


要具体的量化这个减少bug的百分比,不是一件容易的事。


不过伦敦大学与微软研究院的一些学者,发表了一篇相当有影响力的论文。文中指出,15%的github 公开bug,是可以通过Typescript来规避的。而根据在线教育TS使用的实际经验,数据统计,我们发现超过30%的bug都可以通过类型安全来规避。


3.1.2 为什么达到30%


腾讯IMWEB团队《未来可期的TypeScript》


业务中的通常bug可以被分为两类,一类是类型错误(type error)引发的bug,这部分错误中的大多数是可以通过ts来避免的。


另一类是实现错误(spec error)引发的bug,比如对需求没有理解透彻,导致做出来的功能不符合预期,或者有逻辑bug。所以TS能减少的具体的bug比例数字,与类型错误引起的bug在项目总体中的比例有关。


3.2 理由二:提高生产力


3.2.1 如何提高生产力


腾讯IMWEB团队《未来可期的TypeScript》


静态类型,除了保证了类型安全。更重要的是,让你的电脑、软件可以更懂你的代码涵义。从而使得制作更好的生产力工具成为可能。生产力工具的提升,让开发者可以更加愉悦的写代码。从而最终提高生产力。


3.2.2 常用功能


腾讯IMWEB团队《未来可期的TypeScript》


此处主要通过demo展示带TS在VS Code中一些能力。代码提示、引用查询、自动import、代码即文档等。


3.2.3 生产力提高的背后


工具能力的提升只是在表面。相信很多人会有这样的疑问:没错在VS Code里写TS很方便。但是这种不都是IDE本身提供的吗?

腾讯IMWEB团队《未来可期的TypeScript》


事实上,这些能力其实是由TS本身提供的:


1. 与其他编译器不同,TS的编译器不是一个黑盒,而是完全对外开放的。


2. TS的编译器架构,包括了底层了核心Ts编译器,语言服务,并且通过ts server把他所支持的功能都通过api暴露出来。


3. 第三方的工具就可以通过这个api来直接使用ts语言服务的各种功能。


4. 通过这种方式,其他的ide,工具,也可以快速的集成TS的相关能力。这也是为什么即使你使用webStorm也可以获得与VS Code类似的TS开发体验。


3.3 理由三:端到端的类型安全


3.3.1 使用TS之前


腾讯IMWEB团队《未来可期的TypeScript》



图中是一个比较常见的架构。我们有运行在浏览器中的页面代码,它与中间的接入层nodejs服务进行通信,在后台我们还有一个C++服务,它nodejs服务之间用protobuf, 以rpc的形式来进行通信。


这个时候,一旦后台的协议发生更改,是一件非常棘手的事情,因为这里面没有任何类型追踪,我们需要在前端浏览器代码和nodejs代码中全局搜索对应的字段来修改,非常容易改错改漏。


3.3.2 使用TS之后


腾讯IMWEB团队《未来可期的TypeScript》


通过protobuf的TS插件,将请求、返回结构,方法等全都转换为TS。并且在页面代码与node服务代码中进行共享。


腾讯IMWEB团队《未来可期的TypeScript》


当proto协议文件发生更改的时候,只需要重新生成新的TS类型文件,无论是页面代码,还是node服务代码都会自动报错,提示开发者去做对应字段的修改。


3.4 理由四:强大的社区支持


3.4.1 第三方库


腾讯IMWEB团队《未来可期的TypeScript》


因为现如今任何一个前端项目都会引入大量的第三方库。对于这些第三方库,如果作者本身没有提供类型定义怎么办呢?


社区早就有了非常成熟解决方案,DenitelyTyped这个仓库目前是github排名第八的项目,有着超过10000名的代码贡献者,这里面有超过5000个前端库的类型定义。基本上你会用的,都已提供了类型定义。


3.4.2 框架反哺


腾讯IMWEB团队《未来可期的TypeScript》


我们也发现越来越多的,非常有影响力的前端框架的新版本都开始用ts来进行重写了。Angular 2, Vue3等等。


而这些社区中的开发者,都是开源社区最活跃的参与者,他们会将开发过程中遇到的ts的一些问题,通过PR或者反馈的方式再反哺到ts社区中,让ts的生态越来越好。


腾讯IMWEB团队《未来可期的TypeScript》
5
Part4 团队TS引入策略


4.1 确定是否有必要引入


腾讯IMWEB团队《未来可期的TypeScript》


在正式引入之前,第一点还是需要明确一下,你的团队的具体需求。


1. 你的项目规模是怎样的?当然规模越大TS的帮助也就越大。


2. 项目是由存在多人合作或者经常有新人员加入呢?如果回答是yes,TS的使用,可以让你的代码更规范,让新人更快速的熟悉代码。


3. 是否需要长期维护?TS100%可以让你的项目结构更健康,更容易的去重构。


4.2 定点试验


腾讯IMWEB团队《未来可期的TypeScript》


1. 成立实验小组,让这部分人员先行,在项目中进行试点。


2. 这段时间内,要定期的对这部分人员进行问卷调查,看看他们的满意度。


3. 将遇到的疑问,譬如像第三方依赖怎么办之类的问题,梳理成FAQ,以便后续做更大范围的宣导。


4.3 构建迁移


腾讯IMWEB团队《未来可期的TypeScript》


构建迁移,其实非常的简单。通常我们需要处理的就是babel和webpack。这两者现在都利用了TS 的语言服务能力。


1. 如果你的代码需要用babel转换,你可以直接加上babel-ts插件,这样你编译出来的代码就自动会去除掉ts的类型,其他的功能还是走babel的转化逻辑。


2. 更多的时候,你会选择第二种,直接放弃掉babel,使用webpack的ts-loader直接对ts进行编译。


4.3.1 构建优化


腾讯IMWEB团队《未来可期的TypeScript》


TS3.0增加了project reference功能。


1. 你只需要在子文件夹里面,分别建一个新的tsconfg文件。在要引用的tsconfig中加上reference引用到另一个项目。在被引用的文件夹的tsconfig中增加composite为true。


2. 通过这样的配置,当ts在做类型检查的时候,只会检查当面项目的ts文件。保证了检查过程的高效。


3. 当你运行tsc build的时候,它也会进行增量的构建,只有当引用文件发生修改过期的时候,才会重新构建。


4.3.2 Lint迁移


腾讯IMWEB团队《未来可期的TypeScript》


1. 首先在你eslintrc.js文件中引入TS的parser与plugin


2. Extends里面,建议就使用typescirpt-eslint这个包推荐的几种配置


3. 接下来把你团队原来的eslint规则包引入进来,基本上你会发现原来所有eslint规则都是可以正常工作的。你也可以继续使用rules属性来覆盖继承的规则。


4.3.3 依赖迁移


腾讯IMWEB团队《未来可期的TypeScript》


1. 对于那些本身已经用TS来写的依赖,你不需要做任何改变。正常import进来就可以了。但是如果库本身没有自带类型,那你就需要使用denitelyTyped这个库,来把类型当作dev依赖装上就可以了。


2. 然而如果DT里面也找不到类型定义。那你需要做的就是,在d.ts里面declare一下这个module,可以自己给它添加类型定义,最终发布到DT上。


3. 更棘手的情况是类型找到了,但是有错。导致明明我传出正确的参数,还是会看到恼人红线,这里有两种做法:1. 依赖类型声明本身的写法,你可以在import 类型后,通过extends或者merge的能力对源类型进行扩展。2. 修改类型错误,给DT提PR。


4.3.4 代码迁移:混合模式


腾讯IMWEB团队《未来可期的TypeScript》


TS的迁移有两种方式,一种是混合模式,也就是说,把allowJs开关打开,然后一个个的把.js改为.ts,再修复类型。


4.3.5 代码迁移:激进模式


腾讯IMWEB团队《未来可期的TypeScript》


一次性的把所有js后缀全部改成ts。遇到比较难写的类型,或者文件过大的时候。你可以分别使用@ts-ignore或者@ts-nocheck(TS3.7)来忽略掉下一行的类型检查,或者整个文件的类型检查。

腾讯IMWEB团队《未来可期的TypeScript》
6
Part 5 总结


TypeScript之所以取得成功,有一个很重要的原因就是他的定位明确:让JavaScript变得更好,而非取代。


很多没有真正使用过TS的人,对TS的印象往往还停留在“静态类型的JS”。而忽略了“提高生产力”才是TS目前的核心设计目标。


56%的npm开发者都在使用TS,惊人的数字背后是确凿的事实。


所以你还在等什么呢?



7
支持


如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:

  1. 点个「在看」,让更多的人也能看到这篇内容(喜欢不点在看,都是耍流氓 -_-)

  2. 关注我的官网 https://muyiy.cn,让我们成为长期关系