[译] TypeScript 和 Babel:一场美丽的婚姻

栏目: JavaScript · 发布时间: 5年前

内容简介:原文地址:从未变得如此简单,这是 TypeScript 和 Babel 团队长达一年的官方合作成果。本文列举出了4条理由来证明 TypeScript 和 Babel 是完美的一对,以及10分钟内升级到 TypeScript 的步骤指南。我一开始并不理解做这个新 preset 的要解决的需求。

原文地址: TypeScript With Babel: A Beautiful Marriage 作者: Matt Turnbull, Feb 12,2019

[译] TypeScript 和 Babel:一场美丽的婚姻
感谢 Babel 的 TypeScript 插件@babel/preset-typescript ), TypeScript

从未变得如此简单,这是 TypeScript 和 Babel 团队长达一年的官方合作成果。本文列举出了4条理由来证明 TypeScript 和 Babel 是完美的一对,以及10分钟内升级到 TypeScript 的步骤指南。

哈?什么?为什么?

我一开始并不理解做这个新 preset 的要解决的需求。

Babel 和 TypeScript 难道不是2种完全不同的东西吗?Babel 是如何处理 TypeScript 的类型检查的?TypeScript 已经可以像 Babel 那样输出 ES5 了,所以目的是啥?合并 Babe 和 TypeScript 会不会让事情变得更复杂?

经过1个小时的研究,我的结论是: TypeScript 和 Babel 的结合是一场美丽的婚姻。

Let me show you.

1)已经使用了 Babel(或者应该使用)

您一定属于以下3类情况之一:

  1. 已经在使用 Babel,如果不是直接地使用,Webpack 也会将 *.js 文件提供给 Babel (很多脚手架就属于这类情况,包括 creat-react-app )。
  2. 使用 TypeScript 但不使用 Babel。请考虑向项目的 工具 库中添加 Babel,它会带来很多独一无二的功能。继续读下去。
  3. 压根不使用 Babel? 那么现在是时候跳上 Babel 这条船了。

在不会跳出任何错误的情况下编写现代 JavaScript

您的 JavaScript 代码需要在老旧浏览器中运行?没问题,Babel 会将代码转换,并且搞定所有问题。直接使用最新和最棒的特性,而且不用担心任何事情。

TypeScript 的编译器也有相似的功能,是通过设置 target 的值为 ES5ES6 来达到。但是 Babel 的配置利用babel-preset-env 来改善这个功能,而不是锁定一组特定的 JavaScript 功能(ES5,ES6 等等),只需要列出所需要支持的环境即可:

"targets": {
    "browsers": ["last 2 versions", "safari >= 7"],
    "node": "6.10"
}
复制代码

Babel 使用compat-table 来检查需要转换的 JavaScript 特性,以及指定的目标环境所需要的 polyfill。

[译] TypeScript 和 Babel:一场美丽的婚姻
creat-react-app

使用过的一种有意思的技术:在开发过程中,按照最新的浏览器进行编译(为了加快编译速度),而在产品发布阶段按照多种浏览器进行编译(为了兼容性),不错。

Babel 是超级可配置的

想要 JSX?Flow?TypeScript?只要安装插件,Babel 就能处理它们了。这里有相当多的官方插件可供选择,主要涵盖了即将推出的 JavaScript 语法。也有非常多数量的第三方插件: 改进 lodash import加强版 console.log ,或者 清理 console.log 。请在 awesome-babel 列表中发现更多插件。

但是请小心,若插件明确地警告语法错误,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 无法理解这个即将推出的语法。

但是不要有压力,还有替代方案...

Babel Macros

不知道您是否听说过Kent C Dodds,他创造了一个改变 Babel 游戏规则的插件: babel-plugin-macros

与直接向 Babel config 文件中添加插件不同,将宏指令作为依赖安装并且 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
复制代码

Macros 是相当的新的概念,但是很快受到了热捧。尤其是登陆到 create-react-app v2.0 ,JS 中的 CSS 包括styled-jsx,styled-components,和emotion。正在移植 Webpack 插件:raw-loader,url-loader和 filesize-loader。 还有更多列在 awesome-babel-macros 上。

这是最好的部分:不同于 Babel 插件,所有的 Babel 宏指令都和 TypeScirpt 兼容。它们仍可以帮助减少运行时的依赖,避免客户端计算,并且在构建时提前捕获异常。查看这篇帖子获取了解详情。

[译] TypeScript 和 Babel:一场美丽的婚姻
上图演示了一个更好的 console.log: scope.macro

2)只管理一个编译器更轻松

TypeScirpt 需要它自己的编译器————它提供了惊人的类型检查功能。

在灰暗的日子里(Babel 7之前)

将2个独立的编译器(TypeScript 和 Babel)串联在一起是可不是一件容易的工作。编译流程变为: TS > TS 编译器 > JS > Babel > JS (再次)

Webpack 经常用于解决这个问题,调整 Webpack 的配置。将 *.ts 提供给 TypeScript,然后将运行的结果提供给 Babel。但是用哪个 TypeScript loader 呢?2个非常流行的选择是: ts-loaderawesome-typescript-loaderawesome-typescript-loaderREADME.md 中提到,在某些工作量中它可能会比较慢,并且建议使用 ts-loader 配合 HappyPack 或者thread-loader。 ts-loaderREADME.md 文件推荐结合使用 fork-ts-checker-webpack-pluginHappyPack 、thread-loader 以及(或者) cache-loader

够了。。这就是吞没大多数同学的地方,也是大家还给 TypeScript 贴上“太难”标签的原因之一。这不怪大家。

[译] TypeScript 和 Babel:一场美丽的婚姻

光明降临的日子(Babel 7)

只有一个 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 页面:

[译] TypeScript 和 Babel:一场美丽的婚姻

3)更快地编译

Babel 是如何处理 TypeScript 的? 它移除了 TypeScript。

是的,它删除了所有 TypeScript ,将其转换为“常规” JavaScript,并继续使用它高兴的方式。

听起来挺荒唐的,但是这种实现具有两个非常强大的优势。

第一个优势::zap:️快如闪电:zap:️

大多数的 TypeScript 开发者在 devlement/watch 模式中,会遇到非常缓慢的编译速度。你现在正在敲代码,保存文件,接下来是很漫长的等待。。。终于,你看到了你更改的内容。啊哦,不小心写错字了,修改,保存,然后。。。够了!它不仅慢得令人烦躁,还打击了你编程的动力。

我们也不能去责怪 TypeScript 编译器,它在做的工作实在太多了。它在扫描类型定义文件( *.d.ts ),包括 node_modules 里的,以确保你的代码里正确地使用。这就是为什么很多人将 TypeScript 类型检查分为一个独立的进程。然而,Babel + TypeScript 的组合套餐依旧会提供更快的编译,这要归功于 Babel 的优秀的缓存和单文件散发架构。

因此,如果 Babel 剥离了 TypeScript 的代码,那么编写 TypeScript 的意义何在呢?这带来了第二个优势。。。

4)只在当你准备好的时候检查类型错误

现在你正在开心地编程,不假思索地提出解决方案来验证你的想法是否奏效。你保存文件,TypeScript 却对你大喊:

“不!我不会编译这玩意儿的!你的代码在42个不同的文件中出现异常!”

对,你知道它有异常。可能在几个单元测试中已经出现异常了。但是你可能只是想在这里做一个实验。总是持续不断地进行类型安全性检查有时候是挺烦人的。

这就是 Babel 在编译过程中剥离 TypeScript 的第二个优势。编写,保存,然后它会快速编译(速度很快)而不需要进行类型安全性检查。这样就可以在你准备好检查代码错误之前,尽情地去对解决方案做实验。

那如何去检查类型错误呢?添加一段 npm run check-types 脚本来唤起 TypeScript 编译器。我将我的 npm test 命令调整为先检查类型,然后再继续运行单元测试。

这是不是一段完美的婚姻

根据项目公告可以了解到,由于 Babel 的单文件发射架构,有四种TypeScript 特性无法在 Babel 中编译。

不过不用担心,还不算太糟糕。而且当启用 isolatedModules 的配置选项时,TypeScript 将对这些问题做出警告。

1)Namespace

解决方案:不要用!它们已经是过时的了。改用标准的 ES6 module( import / export ),在 推荐的 tslint 规则 中也建议不要使用 namesapce。

2)使用 <newtype>x 语法转换类型

解决方案:改用 x as newtype

3) const 枚举

这个锅没得甩,目前只能用常规的枚举,期待未来能够支持。

4)历史遗留风格的 import/export 语法

比如: import foo = require(...)export = foo

我写 TypeScript 这么多年,就从来没这么写过。谁是这么写的?可别再这么干了!

OK, 准备好尝试一下使用 Babel 来写 TypeScript 了

开始搞起!仅仅需要10分钟。

假定你已经安装了 Babel 7,如果没有,请查看Babel 迁移指南。

1)将 .js 重命名为 .ts

假设文件存储在 /src 目录下:

find src -name "*.js" -exec sh -c 'mv "$0" "${0%.js}.ts"' {} ;
复制代码

2)向 Babel 添加 TypeScript

安装几个依赖:

npm install --save-dev @babel/preset-typescript @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread
复制代码

Babel 配置文件( .babelrcbabel.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'

3)添加 'check-type' 命令

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 + TypeScript = 美丽的婚姻

[译] TypeScript 和 Babel:一场美丽的婚姻

Babel是唯一需要的 JavaScript 编译器,它可以通过配置来处理任何事情。

没有必要让两个 JavaScript 编译器竞争,简化项目配置,并充分利用 Babel 与 ESLint,单元测试,构建系统和项目模板集成在一起的优势。

Babel 和 TypeScript 的组合可以快速编译,并允许在编码时留在免打扰的空间里,并且只有在准备好的时候才检查类型。

预言: TypeScript 将会崛起

根据最新的 Stack Overflow 开发者调查 ,JavaScript 是最流行的语言,TypeScript 落后于第12名。对于TypeScript来说,这仍然是一项伟大的成就,因为它击败了 Ruby,Swift 和 Go。

[译] TypeScript 和 Babel:一场美丽的婚姻

我预测 TypeScript 将在明年进入前10名。

TypeScript 团队正在努力和其他团队合作。这个 Babel preset 是为期一年的合作成果,他们的新焦点是改进ESLint集成。这是一个聪明的举措——利用现有工具的功能,社区和插件。开发编译器和代码检查器去和别人竞争简直是浪费精力。

只需调整我们喜爱的工具的配置即可铺设进入 TypeScript 的路径。TypeScript 入口的障碍已被扫清。

随着VS Code 的普及,开发人员已经设置了一个惊人的 TypeScript 环境。

它现在也集成到 create-react-app v2.0 中,将 TypeScript 以每月20万次下载量的规模提供给用户。

如果你迟迟不愿接触 TypeScript,因为它很难设置,它不再是一个借口,现在是时候去试一试了。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

小程序大时代

小程序大时代

即速应用 / 哈尔滨工业大学出版社 / 2018-10 / 58元

2017年1月9日微信小程序的问世,是中国互联网发展史上的又一个里程碑。支付宝、百度、今日头条等各大巨头的陆续进场,无不证明小程序这种轻应用形态已经成为移动互联网的发展趋势。我们希望可以通过这本书,帮助零基础的小程序爱好者,了解小程序的市场走向和生态发展,学会小程序的制作与运营,读懂小程序这个全新物种。 全书分为入门篇、制作篇、运营篇三大篇章。 入门篇首先揭开小程序的神秘面纱,盘点小程......一起来看看 《小程序大时代》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具