原文地址:TypeScript With Babel: A Beautiful Marriage 做者: Matt Turnbull, Feb 12,2019javascript
@babel/preset-typescript
),
TypeScript 从未变得如此简单,这是 TypeScript 和 Babel 团队长达一年的官方合做成果。本文列举出了4条理由来证实 TypeScript 和 Babel 是完美的一对,以及10分钟内升级到 TypeScript 的步骤指南。
我一开始并不理解这个新 preset 要解决的需求。html
Babel 和 TypeScript 难道不是2种彻底不一样的东西吗?Babel 是如何处理 TypeScript 的类型检查的?TypeScript 已经能够像 Babel 那样输出 ES5 了,因此目的是啥?合并 Babe 和 TypeScript 会不会让事情变得更复杂?java
通过 1 个小时的研究,个人结论是: TypeScript 和 Babel 的结合是一场美丽的婚姻。node
Let me show you.react
您必定属于如下三类状况之一:webpack
*.js
文件提供给 Babel (不少框架模板就属于这类状况,包括 creat-react-app)。须要在老旧浏览器中运行 JavaScript 代码?没问题,Babel 会将代码转换,而且搞定全部问题。直接使用最新和最棒的特性,并且不用担忧任何事情。git
TypeScript 的编译器也有类似的功能,是经过设置 target
的值为 ES5
或 ES6
来达到。可是 Babel 利用 babel-preset-env 来改善这个功能,而不是锁定一组特定的 JavaScript 功能(ES5,ES6 等等),只须要列出所须要支持的环境便可:github
"targets": {
"browsers": ["last 2 versions", "safari >= 7"],
"node": "6.10"
}
复制代码
Babel 使用 compat-table 来检查须要转换的 JavaScript 特性,以及指定的目标环境所须要的 polyfill。web
creat-react-app
使用过的一种有意思的技术:在开发过程当中,按照最新的浏览器进行编译(为了加快编译速度),而在产品发布阶段按照多种浏览器进行编译(为了兼容性),Nice~
想要 JSX?Flow?TypeScript?只要安装插件,Babel 就能处理它们了。这里有至关多的官方插件可供选择,涵盖了大多数即将推出的 JavaScript 语法,也有很是多的第三方插件:改进 lodash import,增强版 console.log,或者 清理 console.log。能够在 awesome-babel 的列表中找到更多插件。typescript
可是请当心,若插件明显地改变了语法,TypeScript 可能会不能解析它。例如,有一个 Babel 插件:@babel/plugin-proposal-optional-chaining,可以实现备受期待的可选链提案 。
const obj = {
foo: {
bar: {
baz: 42
}
}
};
const baz = obj?.foo?.bar?.baz; // 42
const safe = obj?.qux?.baz; // undefined
复制代码
遗憾的是,TypeScript 没法理解这个即将推出的语法。
但不要有压力,还有替代方案...
不知道您是否据说过 Kent C Dodds,他创造了一个改变 Babel 游戏规则的插件:babel-plugin-macros。
它由直接向 Babel config 文件中添加插件,改成把宏指令(macro)做为依赖安装而且 import 到代码中。当 Babel 正在编译的时候,宏指令开始起做用,而且修改代码。
举个例子,在可选链特性正式加入到标准以前,咱们能够先使用 idx.macro 来达到相同的效果。
import idx from 'idx.macro';
const friends = idx(
props,
_ => _.user.friends[0].friends
);
复制代码
编译后:
const friends =
props.user == null ? props.user :
props.user.friends == null ? props.user.friends :
props.user.friends[0] == null ? props.user.friends[0] :
props.user.friends[0].friends
复制代码
Babel Macro 是至关的新的概念,可是很快受到了热捧。尤为是登录到 create-react-app v2.0,JS 中的 CSS 包括 styled-jsx,styled-components,和 emotion。正在移植 Webpack 插件:raw-loader,url-loader和 filesize-loader。 还有更多列在 awesome-babel-macros 上。
最棒的是,不一样于 Babel 插件,全部的 Babel Macro 都和 TypeScirpt 兼容。它们仍能够帮助减小运行时的依赖,避免客户端计算,而且在构建时提早捕获异常。查看这篇帖子获取了解详情。
TypeScirpt 须要它本身的编译器——由于它提供了超棒的类型检查功能。
将两个独立的编译器(TypeScript 和 Babel)串联在一块儿是可不是一件容易的工做。编译流程变成:TS > TS 编译器 > JS > Babel > JS (再次)
。
Webpack 常常用于解决这个问题,调整 Webpack 的配置。将 *.ts
提供给 TypeScript,而后将运行的结果提供给 Babel。可是用哪一个 TypeScript loader 呢?2个很是流行的选择是:ts-loader 和 awesome-typescript-loader。awesome-typescript-loader的README.md
中提到,在某些工做量中它可能会比较慢,而且建议使用 ts-loader 配合 HappyPack 或者 thread-loader。ts-loader 的README.md
文件推荐结合使用 fork-ts-checker-webpack-plugin、HappyPack、thread-loader 以及(或者)cache-loader。
够了。。这就是吞没大多数同窗的地方,也是你们还给 TypeScript 贴上“太难”标签的缘由之一。这不怪你们。
只有一个 JavaScript 编译器难道很差吗?不管代码是否具备 ES2015 特性,JSX,TypeScript,仍是其余疯狂的自定义————编译器都知道要作什么。
我刚刚只是在描述Babel。
经过容许 Babel 做为惟一的编译器来工做,就再也不必利用一些复杂的 Webpack 魔法来管理、配置或者合并两个编译器。
它还精简了整个 JavaScript 生态系统。取代了 ESLint、测试 runner、build 系统,以及开发模板提供的不一样的编译器,它们只须要支持 Babel 便可。而后配置 Babel 来处理具体的需求。向 ts-loader、ts-jest、ts-karma、create-react-app-typescript 等等说再见就好啦,使用 Babel 代替它们。Babel 的支持无处不在,查看 Babel setup 页面:
Babel 是如何处理 TypeScript 的?它移除了 TypeScript。
是的,它删除了全部 TypeScript ,将其转换为“常规” JavaScript,并继续使用它高兴的方式。
听起来挺荒唐的,可是这种实现具备两个很是强大的优点。
第一个优点:⚡️快如闪电⚡️
大多数的 TypeScript 开发者在 devlement/watch 模式中,会遇到很是缓慢的编译速度。你如今正在敲代码,保存文件,接下来是很漫长的等待。。。终于,你看到了你更改的内容。啊哦,不当心写错字了,修改,保存,而后。。。够了!它不只慢得使人烦躁,还打击了你编程的动力。
咱们也不能去责怪 TypeScript 编译器,它在作的工做实在太多了。它在扫描类型定义文件(*.d.ts
),包括node_modules
里的,以确保你的代码里正确地使用。这就是为何不少人将 TypeScript 类型检查分为一个独立的进程。然而,Babel + TypeScript 的组合套餐依旧会提供更快的编译,这要归功于 Babel 的优秀的缓存和单文件散发架构。
所以,若是 Babel 剥离了 TypeScript 的代码,那么编写 TypeScript 的意义何在呢?这带来了第二个优点。。。
如今你正在开心地编程,不假思索地提出解决方案来验证你的想法是否奏效。你保存文件,TypeScript 却对你大喊:
“不!我不会编译这玩意儿的!你的代码在42个不一样的文件中出现异常!”
对,你知道它有异常。可能在几个单元测试中已经出现异常了。可是你可能只是想在这里作一个实验。老是持续不断地进行类型安全性检查有时候是挺烦人的。
这就是 Babel 在编译过程当中剥离 TypeScript 的第二个优点。编写,保存,而后它会快速编译(速度很快)而不须要进行类型安全性检查。这样就能够在你准备好检查代码错误以前,尽情地去对解决方案作实验。
那如何去检查类型错误呢?添加一段 npm run check-types
脚原本唤起 TypeScript 编译器。我将个人 npm test
命令调整为先检查类型,而后再继续运行单元测试。
根据项目公告能够了解到,因为 Babel 的单文件发射架构,有四种TypeScript 特性没法在 Babel 中编译。
不过不用担忧,还不算太糟糕。并且当启用 isolatedModules
的配置选项时,TypeScript 将对这些问题作出警告。
解决方案:不要用!它们已是过期的了。改用标准的 ES6 module(import
/export
),在推荐的 tslint 规则中也建议不要使用 namesapce。
<newtype>x
语法转换类型解决方案:改用 x as newtype
。
这个锅没得甩,目前只能用常规的枚举,期待将来可以支持。
好比:import foo = require(...)
和 export = foo
。
我写 TypeScript 这么多年,就历来没这么写过。谁是这么写的?可别再这么干了!
开始搞起!仅仅须要10分钟。
假定你已经安装了 Babel 7,若是没有,请查看 Babel 迁移指南。
假设文件存储在 /src
目录下:
find src -name "*.js" -exec sh -c 'mv "$0" "${0%.js}.ts"' {} ;
复制代码
安装几个依赖:
npm install --save-dev @babel/preset-typescript @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread
复制代码
Babel 配置文件(.babelrc
或 babel.config.js
):
{
"presets": [
"@babel/typescript"
],
"plugins": [
"@babel/proposal-class-properties",
"@babel/proposal-object-rest-spread"
]
}
复制代码
TypeScript 有几个 Babel 须要了解的额外特性(经过上面列出的2个插件)。
Babel 默认查找 .js 文件,遗憾的是,你还没办法在 Babel 的 config 文件中进行配置。
若是使用 Babel CLI,添加 --extensions '.ts'
。
若是使用 Webpack,向 resolve.extensions
数组中添加 'ts'
。
在 package.json
中添加:
"scripts": {
"check-types": "tsc"
}
复制代码
这条命令只是简单地唤起 TypeScript 编译器(tsc
)。
经过安装 TypeScript 来获取 tsc
:
npm install --save-dev typescript
复制代码
在根目录里添加 tsconfig.json
文件来配置 TypeScript 和 tsc
:
{
"compilerOptions": {
// Target latest version of ECMAScript.
"target": "esnext",
// Search under node_modules for non-relative imports.
"moduleResolution": "node",
// Process & infer types from .js files.
"allowJs": true,
// Don't emit; allow Babel to transform files.
"noEmit": true,
// Enable strictest settings like strictNullChecks & noImplicitAny.
"strict": true,
// Disallow features that require cross-file information for emit.
"isolatedModules": true,
// Import non-ES modules as default imports.
"esModuleInterop": true
},
"include": [
"src"
]
}
复制代码
OK,配置完成。如今运行 npm run check-types
(监听模式:npm run check-types -- --watch
),确保 TypeScript 代码正常运行。你可能会发现一些未知但确实存在的错误,这未必是件坏事,这篇Javascript 迁移指南能够提供一些帮助。
微软的 TypeScript-Babel-Starter 包含其余的设置说明,包括从零安装 Babel,生成类型定义(d.ts)文件,以及将其与 React 一块儿使用。
使用 tslint
于2019年2月更新:使用 ESLint !TypeScript 团队自从1月份开始就在专一于 ESLint 集成。归功于 @typescript-eslint 项目,配置 ESLint 变的很是简单。如需灵感,请查看个人 终极ESLint配置,其中包括 TypeScript,Airbnb,Prettier和 React。
Babel是惟一须要的 JavaScript 编译器,它能够经过配置来处理任何事情。
没有必要让两个 JavaScript 编译器竞争,简化项目配置,并充分利用 Babel 与 ESLint,单元测试,构建系统和项目模板集成在一块儿的优点。
Babel 和 TypeScript 的组合能够快速编译,并容许在编码时留在免打扰的空间里,而且只有在准备好的时候才检查类型。
根据最新的 Stack Overflow 开发者调查,JavaScript 是最流行的语言,TypeScript 落后于第12名。对于TypeScript来讲,这仍然是一项伟大的成就,由于它击败了 Ruby,Swift 和 Go。
我预测 TypeScript 将在明年进入前10名。
TypeScript 团队正在努力和其余团队合做。这个 Babel preset 是为期一年的合做成果,他们的新焦点是改进ESLint集成。这是一个聪明的举措——利用现有工具的功能,社区和插件。开发编译器和代码检查器去和别人竞争简直是浪费精力。
只需调整咱们喜好的工具的配置便可铺设进入 TypeScript 的路径。TypeScript 入口的障碍已被扫清。
随着 VS Code 的普及,开发人员已经设置了一个很是棒的 TypeScript 环境。
它如今也集成到 create-react-app v2.0 中,将 TypeScript 以每个月20万次下载量的规模提供给用户。
若是你迟迟不肯接触 TypeScript,由于它很难设置,它再也不是一个借口,如今是时候去试一试了。