目前 TypeScript 的編譯有兩種方式。一種是使用 TypeScript 自家的編譯器 typescript 編譯(咱們後面會用統一稱爲 TS 編譯器),一種就是使用 Babel + @babel/preset-typescript 編譯。因此,當咱們使用 TypeScript 開發項目的時候,遇到的第一個問題就是,咱們應該選擇哪一種編譯方式?git
文章中提到 TS 編譯器,指代 TS 編譯器自身以及在其之上封裝的各種和打包工具配合的插件es6
作出選擇以前,咱們須要瞭解下它們之間的區別。github
TS 編譯器就不說了,它就是對 TypeScript 語言定製的。這裏咱們先說一下 Babel 編譯。typescript
TypeScript 團隊發佈的文章裏說明了如何使用 Babel 編譯 TypeScript 。同時也提到了,Babel 編譯 TypeScript 是不會作類型檢查的,或者說,全部的類型聲明都會被 Babel 拋棄掉[1];另外,Babel 是不支持編譯部分語法的[2]。babel
部分語法不支持基本能夠忽略,由於主要是一些 TypeScript 不推薦的舊的語法。可是沒有類型檢查就是很棘手了。即便在開發過程當中,編輯器會提示咱們類型錯誤,可是在編譯前,仍是要執行一次統一的類型檢查,就像咱們作 eslint 檢查同樣。因此這個時候你會發現,若是你要使用 Babel 編譯,那麼你必需要配合 TS 編譯器一塊兒使用。由於 TS 編譯器是會有類型檢查的。編輯器
但是明明使用 TS 編譯器就能夠完整的編譯 TypeScript,那爲何還要畫蛇添足的使用 Babel 編譯呢?函數
這個時候就不得不提 Babel 編譯的優點了。工具
Babel 可以根據目標環境轉譯指定語法。這一點 TS 編譯器是不支持的。TS 編譯器只能指定將 TypeScript 編譯爲 es3 es5 es6 或相似的某個 ECMAScript 版本。可是在 Babel 裏經過 @babel/preset-env 你能夠指定目標環境,好比 "targets": { "ie": "11" }
,那麼 Babel 只會編譯 ie11 不支持的語法,全部 ie11 支持的語法 Babel 都不會作轉譯。在編譯的靈活性上,只要你想,你能夠控制 Babel 只編譯你須要編譯的語法。es5
Babel 可以根據目標環境自動添加 polyfill。這一點 TS 編譯器是不支持的。若是是新語法的轉譯,TS 編譯器會添加一些輔助函數。可是任何須要修改運行時環境的 polyfill,TS 編譯器是不會幫你添加的。好比你的代碼中用到了 Promise
Set
Map
或者 Object.assign
Array.includes
,那麼你須要本身手動添加相應的 polyfill。可是在 Babel 裏經過@babel/preset-env ,Babel 會判斷目標環境,而後自動幫你添加全部你須要用到的 polyfill。插件
Babel 有插件機制,而且有着活躍的插件生態。這一點 TS 編譯器是不支持的。TS 編譯器沒有插件系統,並不容許你添加本身的插件。可是在目前的開發中,咱們都或多多少的受益於 Babel 各類各樣的插件,並且不少人也都寫過本身的 Babel 插件,去自定義轉譯規則。
以上就是 Babel 編譯的優點。或許能夠做爲爲何 Babel 要支持編譯 TypeScript 的緣由。若是你還了解其餘 Babel 編譯的優點,記得在評論區留言呀。
若是你去翻閱 TypeScript issues 的話,你會發現很早以前,就有人給 TypeScript 提建議,但願他們可以支持自動的引入 polyfill[3],但願他們可以支持插件機制[4]。可是官方的回覆都是這些並不在他們的考慮範圍內。
另外,若是你去查閱 Babel PR 的話,你會發現,給 Babel 提交代碼支持 TypeScript 的人是 TypeScript 團隊的人[5]。
因此,其實不是 Babel 要主動去支持 TypeScript,而是 TypeScript 團隊須要獲得 Babel 的支持,但願 Babel 可以彌補 TS 編譯器的「缺陷」。
另外一方面,TypeScript 沒有選擇本身去實現自動引入 polyfill,去實現插件系統,其實對你們都是有好處的。由於,TypeScript 沒有必要把 Babel 的能力再去實現一遍,並且若是 TypeScript 要去添加本身的插件系統,那麼本來在 Babel 生態下的各類各樣的插件,在 TypeScript 生態下還要再來一次。
所以,TypeScript 選擇讓 Babel 去支持編譯 TypeScript 纔是最好的選擇。並且,當 TypeScript 和 Babel 結合的時候,或許纔是最完美的。
TS 編譯和 Babel 編譯的優缺點如上。不管如何,TS 編譯器都是必須的。即便使用 Babel 編譯,也應該配合 TS 編譯器一塊兒使用,利用 TS 編譯器作類型檢查,而後使用 Babel 完成轉譯工做。至於你是否應該使用 Babel 編譯,要看你是否須要 Babel 編譯的優點,是否依賴 Babel 生態下的各類插件。
最後附上一個 TypeScript 的 demo 項目 ts-hello。在項目裏你能夠選擇使用 TS 編譯器編譯項目仍是 Babel 編譯項目。你也能夠看到若是使用 Babel 編譯,應該如何跟 TS 編譯器一塊兒配合使用。
最後留一個小問題:既然 Babel 都支持 TS 編譯了,爲何不支持類型檢查呢?是作不到嗎?