- 原文地址:TypeScript With Babel: A Beautiful Marriage
- 原文做者:Matt Turnbull
- 译文出自:掘金翻译计划
- 本文永久连接:github.com/xitu/gold-m…
- 译者:zsky
- 校对者:xionglong58, brilliantGuo
因为 TypeScript 和 Babel 团队官方合做了一年的项目:TypeScript plugin for Babel(@babel/preset-typescript
),TypeScript 的使用变得比以往任什么时候候都容易。这篇文章会告诉你为什么 TypeScript 和 Babel 是完美配对的 4 点缘由,并会教你在 10 分钟内一步步地升级到 TypeScript。javascript
我一开始并不理解这个 preset 的必要性。html
Babel 和 TypeScript 不是两个彻底不同的东西么?Babel 能怎么处理 TypeScript 的类型检查?TypeScript 早已能像 Babel 同样输出 ES5 代码,这有什么意义呢?把 Babel 和 TypeScript 合并起来不是会把事情复杂化么?前端
在几个小时的调研后,个人结论是:java
TypeScript 和 Babel 是美丽的结合。node
让我来告诉你缘由。react
你属于这三个类别之一:android
*.js
文件提供给 Babel(大多数脚手架都是这种状况,包括 create-react-app)你的 JavaScript 代码须要在旧浏览器中运行?没问题,Babel 会转换代码,并且不会出现任何问题。使用最新和最好的功能,无需担忧。webpack
TypeScript 编译器具备相似的功能,可经过将 target
设置为 ES5
或 ES6
来实现。但 Babel 配置经过 babel-preset-env 改进了这方面功能。你能够列出须要支持的环境,而不是锁定一组特定的 JavaScript 功能(ES5,ES6 等):ios
"targets": {
"browsers": ["last 2 versions", "safari >= 7"],
"node": "6.10"
}
复制代码
Babel 使用 compat-table 来检查要转换的 JavaScript 功能以及针对这些特定目标环境作 polyfill。git
花点时间欣赏那个将这个项目命名为 ‘compat-table’ 的天才。
create-react-app 使用了一种有趣的技术:在开发期间以最新的浏览器进行编译(为了速度),并在生产中以更大范围的浏览器进行编译(为了兼容性)。漂亮。
想要 JSX? Flow?TypeScript?只需安装一个插件,Babel 就能够处理它。有大量的 官方插件,主要涵盖即将推出的 JavaScript 语法。 还有不少第三方插件:improve lodash imports,enhance console.log,或 strip console.log。在 awesome-babel 列表中找到更多信息。
不过要当心。若是插件显著改变了语法,那么 TypeScript 可能没法解析它。例如,备受期待的 optional chaining proposal 提议有一个 Babel 插件:
@babel/plugin-proposal-optional-chaining
但不幸的是,TypeScript 没法理解这种更新的语法。
没关系张,有另外一种选择...
你知道 Kent C Dodds 吗?他创造了一个改变游戏规则的 Babel 插件:babel-plugin-macros。
你能够将宏安装为依赖项并将其导入代码中,而不是将插件添加到 Babel 配置文件中。当 Babel 正在编译时,宏会启动,并根据须要修改代码。
来看一个例子。 它使用 idx.macro 来解决痛点,直到 optional chaining proposal 提议经过:
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
复制代码
宏是至关新的,但很快就愈来愈受欢迎。特别是集成在 create-react-app v2.0 后。 CSS in JS 被覆盖:styled-jsx、styled-components 和 emotion。Webpack 插件在被移植中:raw-loader、url-loader 和 filesize-loader。还有更多列在 awesome-babel-macros。
这是最好的部分:与 Babel 插件不一样,全部 Babel 宏都与 TypeScript 兼容。它们还能够帮助减小运行时依赖,避免一些客户端计算,并在构建时提早捕获错误。 查看 此帖子 了解更多详情。
更好的 console.log:scope.macro
TypeScript 须要它本身的编译器 — 它提供了惊人的类型检查超能力。
将两个独立的编译器(TypeScript 和 Babel)连接在一块儿并不是易事。编译流程变为:TS > TS Compiler > JS > Babel > JS (again)
。
Webpack 常常用于解决这个问题。调整 Webpack 配置以将 *.ts
提供给 TypeScript,而后将结果提供给 Babel。可是你使用哪一种 TypeScript loader?两个流行的选择是 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 编译器不是很好吗?不管你的代码是否具备 ES201五、JSX、TypeScript 或疯狂的自定义功能 - 编译器都知道该怎么作。
我只是描述了 Babel。厚脸皮了。
经过容许 Babel 充当单个编译器,不须要使用一些复杂的 Webpack 魔术来管理,配置或合并两个编译器。
它还简化了整个 JavaScript 生态系统。他们只须要支持 Babel,而不是支持不一样编译器的语法检查、测试运行器、构建系统和脚手架。而后,配置 Babel 以知足你的特定需求。告别 ts-node、ts-jest、ts-karma 和 create-react-app-typescript 等,并使用 Babel 支持代替。对 Babel 的支持无处不在,请查看 Babel 设置 页面:
警告!有一个震惊的消息,你可能想坐下来好好听下。
Babel 如何处理 TypeScript 代码?它删除它。
是的,它删除了全部 TypeScript,将其转换为“常规的” JavaScript,并继续以它本身的方式愉快处理。
这听起来很荒谬,但这种方法有两个很大的优点。
第一个优点:️⚡️闪电般快速⚡️。
大多数 Typescript 开发人员在开发/监视模式下经历过编译时间长的问题。你正在编写代码,保存一个文件,而后...它来了...再而后...最后,你看到了你的变动。哎呀,错了一个字,修复,保存,而后...啊。它只是慢得使人烦恼并打消你的势头。
很难去指责 TypeScript 编译器,它在作不少工做。它在扫描那些包括 node_modules
在内的类型定义文件(*.d.ts
),并确保你的代码正确使用。这就是为何许多人将 Typescript 类型检查分到一个单独的进程。然而,Babel + TypeScript 组合仍然提供更快的编译,这要归功于 Babel 的高级缓存和单文件发射架构。
所以,若是 Babel 剥离掉 TypeScript 代码,那么编写 TypeScript 有什么意义呢?这带来了第二个优点...
你为了快速作出一个解决方案来看看你的想法是否有根据,会把一些代码改到一块儿。当你按下保存按钮的时候,TypeScript 向你尖叫:
“不!我不会编译这个!你的代码在 42 个不一样的文件中有问题!”
是的,你知道它已经不能运行了。你可能也破坏了一些单元测试。可是你只是在这一点上进行实验。要在全部时间持续确保全部代码是类型安全的,这一点让人火大。
这是 Babel 在编译期间剥离 TypeScript 代码的第二个优势。你编写代码,保存,而且编译(很是快)而不检查类型安全性。继续尝试解决方案,直到你准备好检查代码是否有错误。这种工做流程可以让你在编码时保持专一。
那么如何检查类型错误?添加一个调用 TypeScript 编译器的 npm run check-types
脚本。我将个人 npm test
命令调整为首先检查类型,而后继续运行单元测试。
根据 公告文章,有四种 TypeScript 功能因为其单文件发射架构而没法在 Babel 中编译。
别担忧,它没有那么糟糕。当启用 isolatedModules
标志时,TypeScript 将对这些问题发出警告。
1)命名空间。
解决方案:不要使用它们!他们已通过时了。请改用行业标准 ES6 模块(import
/ export
)。推荐 tslint 规则 确保命名空间不被使用。
2)使用<newtype>x
语法转换类型。
解决方案:使用 x as newtype
。
3)Const 枚举。
这很羞愧。如今须要使用常规枚举。
4)传统风格的 import / export 语法。
示例:import foo = require(...)
和 export = foo
。
在我多年 TypeScript 的使用中,我从未遇到过这种状况。谁这样编码?停下来!
由 rawpixel.com 拍摄
咱们开工吧!它应该只须要大约 10 分钟。
我假设你设置了 Babel 7。若是没有,请参阅 Babel 迁移指南。
1)将 .js 文件重命名为 .ts
假设你的文件位于 /src
中:
find src -name "*.js" -exec sh -c 'mv "$0" "${0%.js}.ts"' {} ;
复制代码
2)将 TypeScript 添加到 Babel。
安装一些依赖:
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 须要了解的额外功能(经过上面列出的两个插件)。
Babel 默认查找 .js 文件,遗憾的是,这在 Babel 配置文件中是不可配置的。
若是你使用 Babel CLI,添加 --extensions '.ts'
若是你使用 Webpack,添加 'ts'
到 resolve.extensions
数组。
3)添加 “check-types” 命令。
在 package.json
里添加:
"scripts": {
"check-types": "tsc"
}
复制代码
这个命令只是简单地调用 TypeScript 编译器(tsc
)。
tsc
来自哪里?咱们须要安装 TypeScript:
npm install --save-dev typescript
复制代码
为了配置 TypeScript(和 tsc
),咱们须要在根目录下有 tsconfig.json
文件:
{
"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" ] } 复制代码
完成。
好了,设置完成了。如今运行 npm run check-types
(监听模式:npm run check-types -- --watch
)并确保 TypeScript 对你的代码满意。你可能会发现一些你不知道但却存在的错误。这是件好事!这份 从 Javascript 迁移 指南也会给你一些帮助。
Microsoft 的 TypeScript-Babel-Starter 指南包含其余设置说明,包括从头开始安装 Babel,生成类型定义(d.ts)文件,以及将其与 React 一块儿使用。
使用 tslint。
更新(2019 年 2 月):使用 ESlint!自1月份以来,TypeScript 团队一直 专一于 ESLint 集成。因为 @typesript-eslint 项目,很容易配置 ESLint。如需参考,请查看个人 超级 ESLint 配置,其中包括 TypeScript、Airbnb、Prettier 和 React。
由 Akshar Dave 拍摄
Babel 是你须要的惟一一个 JavaScript 编译器。它能够被配置去处理任何事情。
没有必要与两个相互竞争的 JavaScript 编译器斗争。简化你的项目配置,并充分利用 Babel 与语法检查、测试运行器、构建系统和脚手架的惊人集成。
Babel 和 TypeScript 组合能够快速编译,并容许你专一地编码,只有在你准备好时才检查类型。
根据最新的 Stack Overflow 开发者调查,JavaScript 是最流行的语言,TypeScript 排在第 12 位。 对于TypeScript 来讲,这仍然是一项伟大的成就,击败了 Ruby、Swift 和 Go。
我预测 TypeScript 将在明年进入前 10 名。
TypeScript 团队正在努力推广。这个 Babel preset 是为期一年的合做,他们的新焦点是在 改进 ESLint 集成。这是一个聪明的举措 — 利用现有工具的功能、社区和插件。开发有竞争力的编译器和语法检查是浪费精力。
通往 TypeScript 的路径已经被铺平了,咱们只需调整咱们喜好的工具配置便可。进入的障碍已被打破。
随着 VS Code 的普及,开发人员已经设置了一个很棒的 TypeScript 环境。写代码时的自动补全将带来欢乐的泪水。
它如今也集成到 create-react-app v2.0 中,将 TypeScript 展示给每个月有 20 万次下载的用户。
若是你由于设置太难而推迟使用 TypeScript,这再也不是一个借口。是时候试一试了。
若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。