目前 TypeScript 的编译有两种方式。一种是使用 TypeScript 自家的编译器 typescript 编译(咱们后面会用统一称为 TS 编译器),一种就是使用 Babel + @babel/preset-typescript 编译。因此,当咱们使用 TypeScript 开发项目的时候,遇到的第一个问题就是,咱们应该选择哪一种编译方式?git
文章中提到 TS 编译器,指代 TS 编译器自身以及在其之上封装的各种和打包工具配合的插件es6
作出选择以前,咱们须要了解下它们之间的区别。github
TS 编译器就不说了,它就是对 TypeScript 语言定制的。这里咱们先说一下 Babel 编译。typescript
TypeScript 团队发布的文章里说明了如何使用 Babel 编译 TypeScript 。同时也提到了,Babel 编译 TypeScript 是不会作类型检查的,或者说,全部的类型声明都会被 Babel 抛弃掉[1];另外,Babel 是不支持编译部分语法的[2]。babel
部分语法不支持基本能够忽略,由于主要是一些 TypeScript 不推荐的旧的语法。可是没有类型检查就是很棘手了。即便在开发过程当中,编辑器会提示咱们类型错误,可是在编译前,仍是要执行一次统一的类型检查,就像咱们作 eslint 检查同样。因此这个时候你会发现,若是你要使用 Babel 编译,那么你必需要配合 TS 编译器一块儿使用。由于 TS 编译器是会有类型检查的。编辑器
但是明明使用 TS 编译器就能够完整的编译 TypeScript,那为何还要画蛇添足的使用 Babel 编译呢?函数
这个时候就不得不提 Babel 编译的优点了。工具
Babel 可以根据目标环境转译指定语法。这一点 TS 编译器是不支持的。TS 编译器只能指定将 TypeScript 编译为 es3 es5 es6 或相似的某个 ECMAScript 版本。可是在 Babel 里经过 @babel/preset-env 你能够指定目标环境,好比 "targets": { "ie": "11" }
,那么 Babel 只会编译 ie11 不支持的语法,全部 ie11 支持的语法 Babel 都不会作转译。在编译的灵活性上,只要你想,你能够控制 Babel 只编译你须要编译的语法。es5
Babel 可以根据目标环境自动添加 polyfill。这一点 TS 编译器是不支持的。若是是新语法的转译,TS 编译器会添加一些辅助函数。可是任何须要修改运行时环境的 polyfill,TS 编译器是不会帮你添加的。好比你的代码中用到了 Promise
Set
Map
或者 Object.assign
Array.includes
,那么你须要本身手动添加相应的 polyfill。可是在 Babel 里经过@babel/preset-env ,Babel 会判断目标环境,而后自动帮你添加全部你须要用到的 polyfill。插件
Babel 有插件机制,而且有着活跃的插件生态。这一点 TS 编译器是不支持的。TS 编译器没有插件系统,并不容许你添加本身的插件。可是在目前的开发中,咱们都或多多少的受益于 Babel 各类各样的插件,并且不少人也都写过本身的 Babel 插件,去自定义转译规则。
以上就是 Babel 编译的优点。或许能够做为为何 Babel 要支持编译 TypeScript 的缘由。若是你还了解其余 Babel 编译的优点,记得在评论区留言呀。
若是你去翻阅 TypeScript issues 的话,你会发现很早以前,就有人给 TypeScript 提建议,但愿他们可以支持自动的引入 polyfill[3],但愿他们可以支持插件机制[4]。可是官方的回复都是这些并不在他们的考虑范围内。
另外,若是你去查阅 Babel PR 的话,你会发现,给 Babel 提交代码支持 TypeScript 的人是 TypeScript 团队的人[5]。
因此,其实不是 Babel 要主动去支持 TypeScript,而是 TypeScript 团队须要获得 Babel 的支持,但愿 Babel 可以弥补 TS 编译器的“缺陷”。
另外一方面,TypeScript 没有选择本身去实现自动引入 polyfill,去实现插件系统,其实对你们都是有好处的。由于,TypeScript 没有必要把 Babel 的能力再去实现一遍,并且若是 TypeScript 要去添加本身的插件系统,那么本来在 Babel 生态下的各类各样的插件,在 TypeScript 生态下还要再来一次。
所以,TypeScript 选择让 Babel 去支持编译 TypeScript 才是最好的选择。并且,当 TypeScript 和 Babel 结合的时候,或许才是最完美的。
TS 编译和 Babel 编译的优缺点如上。不管如何,TS 编译器都是必须的。即便使用 Babel 编译,也应该配合 TS 编译器一块儿使用,利用 TS 编译器作类型检查,而后使用 Babel 完成转译工做。至于你是否应该使用 Babel 编译,要看你是否须要 Babel 编译的优点,是否依赖 Babel 生态下的各类插件。
最后附上一个 TypeScript 的 demo 项目 ts-hello。在项目里你能够选择使用 TS 编译器编译项目仍是 Babel 编译项目。你也能够看到若是使用 Babel 编译,应该如何跟 TS 编译器一块儿配合使用。
最后留一个小问题:既然 Babel 都支持 TS 编译了,为何不支持类型检查呢?是作不到吗?