1. 程式人生 > >理解Flow靜態類型檢查

理解Flow靜態類型檢查

著名 cti 黑點 png 新項目 ets 合規 AC 第三方庫

一、為什麽需要引入類型檢查?

  JS作為一個弱類型語言,一個著名的黑點是它很容易就寫出非常隱蔽的隱患代碼,在編譯期甚至運行時看上去都不會報錯,但是可能會發生各種各樣奇怪的和難以解決的bug。類型檢查是當前動態類型語言的發展趨勢,JS的強類型超集TypeScript已經有了相當的知名度,吸引了大量開發者的學習興趣,並且大部分開發者計劃繼續了解或者使用。

  所謂類型檢查,就是在編譯期盡早發現(由類型錯誤引起的)bug,又不影響代碼運行(不需要運行時動態檢查類型),使編寫js具有和編寫Java等強類型語言相近的體驗。它可以:

  1、使得大型項目可維護

  2、增加代碼的可讀性

  3、通常會有更好的IDE支持

二、Flow是什麽?

  Flow是一個由Facebook出品的JavaScript靜態類型檢查工具,它與Typescript不同的是,它可以部分引入,不需要完全重構整個項目,所以對於一個已有一定規模的項目來說,遷移成本更小,也更加可行。除此之外,Flow可以提供實時增量的反饋,通過運行Flow server不需要在每次更改項目的時候完全從頭運行類型檢查,提高運行效率。

  Flow和Typescript都是給Javascript增加類型檢查的優秀解決方案,兩者的簡單對比如下:

技術分享圖片

  兩者在代碼語法上有大量相似的地方,除了對於一些數據類型的支持不一樣,具體請查看Flow的文檔。關於Flow和Typescript的比較,可以簡單總結為:對於新項目,可以考慮使用TypeScript或者Flow,對於已有一定規模的項目則建議使用Flow進行較小成本的逐步遷移來引入類型檢查。

三、Flow 是如何做到類型檢查的呢?

  在 C#/Java 等強類型語言中,所有的變量、屬性、參數是需要對其定義類型的,也需要對函數的返回值進行類型定義。這樣,在程序編譯過程中,編譯器就會進行類型檢查,如果類型不匹配,將會終止編譯。也就是說,變量存儲的數據自始至終必須是一種類型、函數接收的變量類型也被固定,如果在調用函數時傳遞其它類型,編譯會被中斷。

  第一步:我們要模仿 C#/Java 之類的語言,在編碼過程中對類型進行定義。舉個例子:

function getStringLength(str: string):number {
    const len: number = str.length;
    
return len; }

  我們寫了一段簡單的根據 Flow 的規則,進行類型聲明的代碼。雖然看起來沒有什麽用,但可以簡單講述如何定義類型了。這個函數接收一個 string 類型的參數,參數名為 str,函數的返回值是 number 類型。定義了一個類型為 number 的常量 len,它的值為 str 的長度,並且將其返回。

  第二步:通過 Flow 提供的工具進行類型檢查。如果有類型不匹配的地方,工具會提示錯誤。

  第三步:但是,發布到線上的代碼是不能加類型聲明的,因為這樣不符合規範,瀏覽器也不認。所以,我們需要對源代碼進行一次編譯,將所有聲明的類型去掉,像正常的 JS 代碼一樣了。上面的代碼編譯過後將會變成:

function getStringLength(str) {
    const len = str.length;
    return len;
}

四、Flow的作用

  一個簡單的demo如下。

技術分享圖片

  運行Flow命令flow,這個demo的運行結果如下圖所示:

技術分享圖片

  對於需要使用 Flow 進行類型檢查的 js 文件,在開頭加入 @Flow 註釋,即可引入Flow。通過demo可以看到,Flow可以幫助找出由於不合理的類型操作引起的錯誤,包括運算符操作,函數參數類型和返回值類型等。Flow也支持自定義類型聲明,泛型聲明等類型語言相關的操作。   /* @flow */很重要,在文件中添加這段註釋,告訴Flow,該文件是需要進行類型檢測。

五、類型檢查工具對團隊有什麽好處?

  通過在一個Vue技術棧的實際業務項目中引入Flow,我們大致獲得了這些收益:

  1. 幾乎消滅了由函數數據類型引起的bug
  2. 無需額外的關於變量、參數、返回值類型的註釋,可以讓讀者了解必要的附加信息
  3. 大量減少由於使用第三方庫不當引起的類型錯誤
  4. 可以在CI系統中集成
  5. 工具鏈配置成本比較低,只需要很少的工作量即可達到這些效果

  關於類型檢查工具,讀者可能需要考慮的問題,回答如下表所示。

技術分享圖片

理解Flow靜態類型檢查