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

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

内容简介:原文地址:从未变得如此简单,这是 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,因为它很难设置,它不再是一个借口,现在是时候去试一试了。


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

查看所有标签

猜你喜欢:

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

The Algorithmic Beauty of Plants

The Algorithmic Beauty of Plants

Przemyslaw Prusinkiewicz、Aristid Lindenmayer / Springer / 1996-4-18 / USD 99.00

Now available in an affordable softcover edition, this classic in Springer's acclaimed Virtual Laboratory series is the first comprehensive account of the computer simulation of plant development. 150......一起来看看 《The Algorithmic Beauty of Plants》 这本书的介绍吧!

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

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换