在這篇博文中,我將對三種程式語言的優缺點進行闡述,分別是:JavaScript、TypeScript以及ReasonML。本文的內容基於最近在一些較小的實際項目上使用TypeScript和ReasonML的經驗以及多年的JavaScript經驗。
1. 靜態類型的優缺點
優點:
文檔:對於大多數代碼,記錄參數類型是非常有用的,這樣可以方便區分調用者和被調者。
好處遠不止這些。當我重新訪問舊的JavaScript代碼庫來添加靜態類型時,我可能已經忘了它是如何工作的了。有了這些類型,可以更清楚地說明一切是如何運行的。例如,為了給某函數的參數添加類型注釋,我經常不得不訪問它的調用位置。也就是說,類型暗示了「如何使用這個函數?」的信息。
編輯器中的自動補齊功能可以說是「更好的文檔」。這意味著在使用API時,可以減少查閱文檔的頻率(良好的注釋也是很有幫助的)。例如,當我在2006年開始DOM編程時,我是通過GWT(基於Java,且出於多種原因,是當時最流行的解決方案)實現的。由於Eclipse的自動補齊功能,探索和學習DOM API變得十分有趣。
一種快速檢驗參數類型的方法。對某些函數(看起來像不必要的樣板代碼)添加程序化類型檢驗時,我會嘗試在JavaScript中使用靜態類型。
有助於重構(在枚舉中添加成員等)。
缺點:
需要花時間來學習。
這是一個複雜的附加層,需要在不同的層級上再次編寫代碼。
表達受限。如果使用了泛型、co-variance和contra-variance(例如,一個字符串數組不是一個對象數組的子類型)等等,那麼一切將變得複雜。
無法阻止錯誤的出現。至少目前研究表明是這樣的。根據我的經驗,確實可以捕捉某類錯誤(例如,沒有驗證null)。但是如果採用單元測試而不是添加靜態類型的話,或許我能夠更早地捕捉到它們。所以要檢驗較為嚴重的錯誤時,最好進行測試。
喪失可交互性且編譯需要時間。另一方面,在JavaScript生態系統中,避免編譯幾乎是不可能的。
2. ReasonML
如果想體驗靜態類型提供的最佳功能,請使用ReasonML(或者OCaml,ReasonML基於此開發的)。例如,幾乎所有的語言特性都是經過精心設計的,因此只需要最少量的類型注釋即可(通過支持類型推斷)。
令人印象深刻的是,儘管時間已經久遠(尤其是對編輯器的支持),一些重要的部分仍在更新:更好地支持Promises、迭代和異步迭代;改進名為Belt的標準庫;改進JavaScript的互用性(這已經很不錯了,但比我想要的複雜多了);更好地支持Unicode字符串。
ReasonML的構建時間非常短,比TypeScript快得多,這絕對是個優勢。
它綁定了一些JavaScript庫,但選擇仍然有限:請參閱Reason Package Index。
可以選擇原生。例如,Jared Forsyth用ReasonML編寫了遊戲Gravitron,可以在Android,IOS,web和macOS上運行。
有關ReasonML的更多信息,請參閱「探索ReasonML和函數式編程」(可以免費在線閱讀)。
3. TypeScript
TypeScript的類型系統比我預期的更輕量級。比起Java,它更像FP。例如,假設創建一個接口,這個接口將「匹配」由該接口描述的形狀的所有對象。你可以隨時引入接口而無需改動現有的代碼。
這個類型系統非常強大和直觀。鑑於聯合類型(union types)、交叉類型(intersection types)以及可辨識聯合類型(discriminated union types),你可以將許多慣用的JavaScript類型變成靜態化類型。
支持編輯器(如Visual Studio Code,WebStorm等),都非常好用。
許多npm軟體包要麼帶有靜態類型定義,要麼具有易於安裝的外部定義。更多相關信息,請參閱DefinitelyTyped。
通常,JavaScript互用性非常好。但有一個例外:通過對象字面量來模擬命名參數不必要對類型靜態化(更多信息)。
總結:相比JavaScript和ReasonML的特性,TypeScript佔據了很好的中間地帶。我很想了解它在大型項目中的效果如何。
4. JavaScript
整個生態系統在不斷地推陳出新(如Babel等)。
可以通過npm獲取各類兼容性庫。
可以隨時更新動態。
可以選擇在沒有構建步驟的情況下探索和創建代碼。
有關JavaScript的更多信息,請參閱我的系列書籍「探索JS」(可以免費在線閱讀)。
5. 結論:JavaScript的生態系統比以往更強大
是否使用靜態類型取決於個人。我的建議是:
用你喜歡和熟悉的那類語言。
對目前正在使用的語言的優缺點有所認知。
就個人而言,一旦項目增長超過一定規模(或者我預計它最終會變得那麼大),我就開始使用某種靜態類型。
目前,JavaScript生態系統的優勢和多樣性令人驚嘆:你可以根據需求(以及不同程度的工作)在JavaScript、ReasonML和TypeScript之間切換。它們可以共享一些工具、庫以及語法。例如,當使用ReasonML需要快速模板解決方案時,我可以通過npm使用基於JavaScript的EJS庫。
最後,除此之外還有許多其他好的選擇:靜態類型檢查器Flow,函數式程式語言Elm等。
英文原文:http://2ality.com/2018/03/javascript-typescript-reasonml.html