- 原文地址: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、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。