做者:滴滴公共前端團隊 - Jjavascript
不少人都開始一上來就應用到了 Vue.js 2.*,但並非全部人都會發覺 Flow 的存在,其實熟悉 react 源碼的應該不會陌生。因此呢,今天咱們來普及一下這個東西到底對咱們的工程成本有什麼收益呢?
它和 Babel 還有咱們內部經常使用的 ESlint 有什麼插件支持?
它和 Crockford 的 JSLint 或者後面的 JSHint 有什麼區別?html
facebook 推出的 js 靜態類型檢查工具。前端
flow能夠在代碼運行前對類型錯誤進行檢查,包括:java
- 類型錯誤
- 對null的引用
- 以及可怕的 「undefined is not a function」
flow 容許咱們給變量添加類型
安裝:
因爲 flow 是用 OCaml 語言寫的,npm 上只有對應的二進制包。react
npm install --save-dev flow-bin複製代碼
1.基本使用git
安裝完成後咱們在要執行靜態檢查的文件跟目錄下執行一下 flow init ,以後會發現多處一個.flowconfig文件,這個文件告訴 Flow 在這個目錄下開始檢測。此外 .flowconfig 文件能夠進行一下更爲高級的配置,好比僅包含一些目錄、忽略一下目錄等等(更深刻的瞭解,請戳官網)。 github
對於須要使用 flow 進行類型檢查的 js 文件,在開頭加入 @flow 的註釋shell
/* @flow */ 只要帶有這個註釋,都會進行類型檢測
或者
/* @flow weak */ 只對有加類型註解的變量進行類型檢測複製代碼
例如:npm
/* @flow */
function multiple10 (num) {
return num * 10
}
multiple10('20')
function getLength (str) {
return str.length
}
getLength('3')
getLength([1,2,3])複製代碼
接下來執行 flow check 看一下結果json
3: return num * 10
^^^ string. The operand of an arithmetic operation must be a number.
Found 1 error複製代碼
multiple10 函數中的類型轉換被 flow 標記出。
2.類型註解
注意上面例子中 flow 的報錯,只有 multiple10 中靜態類型錯誤被檢測中。對於 getLength 函數中參數 str 的類型是什麼呢? 從函數自己來分析,只要包含 length 屬性就都是合法的。 對於這種狀況則能夠爲其添加「類型註解」,來明確的告訴 flow 這個值的類型。
function getLength (str: string) {
return str.length
}
getLength('3')
getLength([1,2,3])複製代碼
再來運行一下 flow check , 這時結果會提示咱們[1,2,3]這個參數類型不對。
12: getLength([1,2,3])
^^^^^^^ array literal. This type is incompatible with the expected param type of
8: function getLength (str: string) {
^^^^^^ string複製代碼
3.自定義類型
不少時候,除了 number 、 string 這些基礎類型外,咱們還會有一些自定義的類型,好比:
var someData = {
id: 1,
text: '選項1'
}複製代碼
這時候能夠在一個單獨的文件中將 someData 申明瞭一個自定義類型。方式以下:
/* /decls/data.js.flow */
declare type SomeData = {
id: number;
text: strin;
}複製代碼
而後在 .flowconfig 文件中引入該申明文件
[libs]
decls/複製代碼
在大型項目中,若是每修改完代碼,就執行如下 flow check ,而後等待看結果,顯然會被逼瘋的。flow 爲咱們提供了一個 flow server ,支持在後臺運行,而且只監測有修改的文件。方法很簡單,只有一個命令
$> flow # 開啓一個後臺服務,輸出首次檢測結果
$> flow # 第二次使用flow,鏈接正在運行的後臺服務,輸出檢測結果
$> flow stop # 關閉flow server複製代碼
因爲 flow 中類型註解的語法不屬於 javascript 規範中的內容。因此在最終的代碼中,咱們須要移除flow的內容。flow 提供了 flow-remove-types 和 babel 插件兩種方式,推薦使用 babel 插件來完成這項工做。
flow-remove-types
這種方法比較簡單粗暴: 安裝 flow-remove-types,而後執行命令。
$> npm install -g flow-remove-types
$> flow-remove-types src/ --out-dir build/複製代碼
babel插件
安裝 babel 插件
$> npm install babel-plugin-transform-flow-strip-types複製代碼
babel 的 plugin 中加入該插件
{
"presets": ["es2015", "stage-2"],
"plugins": ["transform-runtime", "transform-flow-strip-types"],
"comments": false
}複製代碼
注意:在 babel6 的 babel-preset-react 的插件中已經內置了 transform-flow-strip-types(flowtype.org/docs/syntax…),若是使用了 babel-preset-react 那麼無需再引入transform-flow-strip-types
eslint-plugin-flowtype 插件,可讓咱們在 eslint 代碼檢查中加入 flow 的書寫規範化檢查。使用方式也很簡單:
安裝
$> npm install eslint-plugin-flowtype複製代碼
{
"extends": [
"standard",
"plugin:flowtype/recommended"
],
"plugins": [
"flowtype"
]
}複製代碼
完成後咱們來看看效果。下面的代碼
function getLength (str:string) {
return str.length
}
getLength('3')複製代碼
eslint 檢查結果會拋出一個錯誤:類型註解的冒號後面丟失了空格。
✘ https://google.com/#q=flowtype%2Fspace-after-type-colon There must be a space after "str" parameter type annotation colon
/Users/didi/xiaoju/src/static-h5-src/750/driver/feedback/src/main.js:2:21
function getLength (str:string) {
^
✘ 1 problem (1 error, 0 warnings)複製代碼
由於推薦的規範中:類型註解冒號後須要一個空格
"rules": {
...
"flowtype/space-after-type-colon": [
2,
"always"
],
...
}複製代碼
flow type 規範配置如:函數返回類型是否必須、類型註解冒號先後的空格、自定義的type 的名稱的命名方式等等,官方給出了很詳細說明和例子。注:針對flow的的規範規則配置前添加「flowtype/」
配置名稱 | 做用 | |
---|---|---|
boolean-style | 類型註解中布爾值使用boolean仍是bool | |
define-flow-type | 將類型註解標記爲已定義,no-undef的檢查中不會出現報錯 | |
delimiter-dangle | Object和Tuple類型定義中分隔符使用規範 | |
generic-spacing | 泛型對象的尖括號中類型先後的空格規範 | |
space-before-generic-bracket | 泛型對象的尖括號前的空格規範 | |
no-dupe-keys | object類型的定義中是否有重複的屬性值 | |
no-primitive-constructor-types | 禁止使用原生的類型 | |
no-weak-types | 是否可使用弱類型any、Object、Function | |
object-type-delimiter | Object類型定義中,屬性以前分割符爲分號/逗號(注:該屬性已被廢棄,須要使用分號來分割) | |
require-parameter-type | 函數的參數是否須要類型註解 | |
require-return-type | 函數返回值是否須要類型註解 | |
require-valid-file-annotation | 文件開頭@flow的寫法 | |
require-variable-type | 什麼樣的變量是須要類型註解 | |
semi | 使用type自定義類型語句結尾是否須要分號結尾 | |
sort-keys | Object類型定義中屬性排列順序 | |
space-after-type-colon | 類型註解分號後的空格規範 | |
space-before-type-colon | 類型註解分號前的空格規範 | |
type-id-match | 使用type自定義類型的名稱規範 | |
union-intersection-spacing | union類型、intersection類型鏈接符號\ | 、&之間的空格規範 |
use-flow-type | 將經過declare定義的自定義類型標記爲已經被使用過,no-unused-vars的檢查中不會出現報錯 |
文中一些中文詞直接從英文文檔中翻譯過來,可能有不許確的地方,這裏給出原文,避免歧義。
自定義類型:原文爲 type aliases, 相似C語言中的typedef,能夠爲已有類型定義一個新的名稱,或將一個複雜類型進行封裝,如
type a = Array<String>
type Person = {
name: string,
age: number
};複製代碼
flow 官網(關於 flow的各類用法官網給出了詳細的例子):flowtype.org/
flow 簡短教程:www.youtube.com/watch?v=xWM…
「掘金技術徵文」活動:gold.xitu.io/post/58522d…
歡迎關注DDFE
GITHUB:github.com/DDFE
微信公衆號:微信搜索公衆號「DDFE」或掃描下面的二維碼