TypeScript 遭庫開發(fā)者嫌棄:類型簡直是萬惡之源
在今年《2022 前端開發(fā)者現(xiàn)狀報告》中顯示, 84% 受訪者表示使用過 TypeScript,可見這門語言已被越來越多的前端開發(fā)者所接受。他們表示,TypeScript 讓 Web 開發(fā)變得輕松——不用在 IDE 和瀏覽器之間來回多次切換,來猜測為什么“undefined is not a function”。
然而,本周 redux-saga 的工程師 Eric Bower 卻在一篇博客中提出了不同意見,他站在庫開發(fā)者的角度,直言“我很討厭 TypeScript”,并列舉了五點理由。這篇博客發(fā)布后,隨即引發(fā)了贊同者和反對者的激烈討論,其中,反對者主要認為文中的幾點理由只能作為開發(fā)人員的意見,而且并沒有提供證明實質性問題的具體例子。
redux-saga 是一個 庫(Library),具體來說,大部分情況下,它是以 Redux 中間件的形式而存在,主要是為了更優(yōu)雅地管理 Redux 應用程序中的副作用(Side Effects)。
以下為 Eric 原文譯文:
作為端開發(fā)者,其實我挺喜歡 TypeScript,它大大削減了手動編寫自動化測試的需求,把勞動力解放出來投入到更能創(chuàng)造價值的地方??傊?,任何能弱化自動化測試工作量的技術,都是對生產力的巨大提升。
但從庫開發(fā)的角度來看,我又很討厭 TypeScript。它煩人的地方很多,但歸根結底,TypeScript 的原罪就是降低庫開發(fā)者的工作效率。從本質上講,TypeScript 就是把復雜性從端開發(fā)者那轉移給了庫開發(fā)者,最終顯著增加了庫開發(fā)流程側的工作負擔。
說明文檔
端開發(fā)者可太幸福了,TypeScript 給他們準備了完備的說明文檔和博文資料。但在庫開發(fā)者這邊,可用的素材卻很少。我能找到的最接近庫開發(fā)需求的內容,主要集中在類型操作上面。
這就讓人有種強烈的感覺,TypeScript 團隊覺得庫開發(fā)者和端開發(fā)者并沒什么區(qū)別。當然有區(qū)別,而且很大!
為什么 TypeScript 的網(wǎng)站上沒有寫給庫開發(fā)者的指南?怎么就不能給庫開發(fā)者準備一份推薦工具清單?
很多朋友可能想象不到,為了在 Web 應用和庫中找到“恰如其分”的類型,我們得經歷怎樣的前列。對端開發(fā)者來說,Web 應用開發(fā)基本不涉及條件類型、類型運算符和重載之類的構造。
但庫開發(fā)者卻經常跟這些東西打交道,因為這些構造高度動態(tài),會把邏輯嵌入到類型當中。這就讓 TypeScript 調度起來令人頭痛萬分。
調試難題
庫開發(fā)者是怎么對高度動態(tài)、大量使用的條件類型和重載做調試的?基本就是硬著頭皮蠻干,祈禱能順利跑通。唯一指望得上的,就是 TypeScript 編輯器和開發(fā)者自己的知識儲備。換個類型,再看看最終結果,如此循環(huán)往復。據(jù)我所知,大家似乎都是在跟著感覺走,并沒有任何穩(wěn)定可靠的科學方法。
對了,庫開發(fā)者經常會用到 TypeScript playground,用來隔離掉類型邏輯中那些離散的部分,借此找出 TypeScript 解析為某種類型的原因。Playground 還能幫助我們輕松切換 TypeScript 的版本和配置。
但這還不夠,遠遠不夠。我們需要更稱手的生產工具。
太過復雜
我跟 redux 打過不少交道,redux-toolkit 確實是個很棒的庫,開發(fā)者可以用它查看實際代碼庫中的類型是如何正確完成的。而問題在于,雖然它能把類型搞得很清楚,但復雜度也同樣驚人。
- createAction #1
- createAction #2
這還只是一例,代碼庫中充斥著更多復雜的類型。此外,大家還要考慮到類型和實際代碼數(shù)量。純從演示出發(fā)、忽略掉導入的代碼,該文件中只有約 10% 的代碼(在全部 330 行中只占 35 行)能被轉譯成 JavaScript。
編碼指南經常建議開發(fā)者不要使用嵌套三元組。但在 TypeScript 中,嵌套三元組成了根據(jù)其他類型縮減類型范圍的唯一方法。是不是鬧呢……
測 試
因為可以從其他類型生成類型,而且各類型都有很高的動態(tài)特性,所以任何生產級別的 TypeScript 項目都得經歷專門的一類測試:類型測試。而且單純對最新版本的 TypeScript 編譯器進行類型測試還不夠,必須針對以往的各個版本全部測試。
這種新的測試形式才剛剛起步,可用工具少得可憐,而且相當一部分要么被放棄了、要么只保持著最基本的維護。我之前用過的庫有:
- DefinitelyTyped-tools
- sd
- dtslint (moved)
- typings-checker (deprecated)
看得出來,類型測試工具的流失率很高。而且因為難以遷移,我有些項目直到現(xiàn)在還在使用早就被棄用的庫。
當然,其中的 dtslint 和 tsd 算是相對靠譜,但它們互為補充、而非擇一即可。為什么我們需要兩款工具才能完成同一類工作?這個問題很難回答,實際使用體驗也是相當難受。
維 護
類型會給庫添加大量代碼。在初次為某個項目做貢獻時,首先需要了解應用程序邏輯和類型邏輯,這直接就讓很多打算參與的朋友望而卻步了。我就幫忙維護過 redux-saga,項目近期發(fā)布的 PR 和 issue 主要就集中在類型身上。
我發(fā)現(xiàn)相較于編寫庫代碼,我花在類型調整上的時間要多得多。
我精通 TypeScript,但還沒到專家那個水平。在經歷了幾年的 TypeScript 編程之后,作為一名庫開發(fā)者,我還是覺得自己用不明白 TypeScript。所以,精通好像成了 TypeScript 的準入門檻。這里的萬惡之源就是類型,它讓 js 庫維護變得困難重重,斷絕了后續(xù)開發(fā)者的貢獻參與通道。
總 結
我認可 TypeScript 的成績,也欽佩它背后的開發(fā)團隊。TypeScript 的出現(xiàn)徹底改變了前端開發(fā)的格局,任何人都不能忽視這份貢獻。
但作為庫開發(fā)者,我們需要:
- 更好的說明文檔。
- 更好的工具。
- 更易用的 tsc。
不管怎么說,靠研究 TypeScript 編譯器源代碼才能搞清楚一段代碼為什么會被解析成特定類型,也實在是太離譜了。