.flowconfig [options]

豐富多元的 Flow options

.flowconfig 中的 [options] 項目就是對 Flow 的各種設定 使用 key-value 一對一對的定義,像是這樣:

[options]
keyA=valueA
keyB=valueB

若是沒有被定義的項目則會使用預設值, 有些 options 選項可以在 flow 的 command line 中指定哦!像是 --lazy-mode --temp-dir 等等的。

可用 options 列表

新版不再支援、不推薦使用列表

all ( boolean )

設定為 true 的話會檢查專案下所有檔案,而不僅僅是標注了 // @flow 的檔案 預設值是 false

babel_loose_array_spread ( boolean )

設定為 true 將會只允許型別為 Array 的進行 JavaScript spread 動作 ( 也就是型別為 MapSet 的都不行)。 這個的使用場景通常是 Babel 有開起來 loose mode 的時候會比較有用。

預設是 false

// @flow
const set = new Set();
const value = [...set]; // 若 babel_loose_array_spread=true 會錯。

emoji ( boolean )

設定為 true 的話 Flow 在忙碌的時候會出現一些 emoji 表情符號

預設是 false

Please wait. Server is initializing (👻 parsed file ...

exact_by_default ( boolean )

顧名思義,若是設定為 true 的話,會預設要求精確匹配型別,( 參考 Exact object types )

// @flow
type Person {
name: string,
age: number,
}
// exact_by_default=true 的話會報錯, false 的話會通過
const person001: Person = {
name: 'Wayne',
age: 26,
foo: 'test',
}

預設為 false

experimental.const_params ( boolean )

設定為 true 的話,Flow 會限制我們不可以改變 function 接收到的參數,也就是把每個接收到的參數都當成 const

// @flow
function sum(a: number, b: number) {
a = 123; // 若是 experimental.const_params=true 會報錯,為 false 的話會通過
return a + b;
}

預設為 false ( 看起來這個在未來專案內都可以考慮設定為 true ^^ )

include_warnings ( boolean )

設定為 true 的話 Flow 的 command line 訊息將會包含 warning 訊息, 預設是不顯示的 ( 如果要看 warning 訊息的話,透過 IDE 的整合介面顯示是比較舒服的哦! )

.flowconfig
include_warnings.js
.flowconfig
[lints]
sketch-null=warn
[options]
include_warnings=true
include_warnings.js
// @flow
function foo(bar: ?bool) {
if (bar) {
// ...
} else {
// ...
}
}

執行 flowflow status 指令進行除錯就可以看到 warning 訊息囉!!

預設為 false

lazy_mode ( fs | ide | watchman | none )

todo...

log.file ( string )

指定 log 檔案存放位置

預設在 /tmp/flow/<escaped root path>.log 像是我有一個 Flow 專案叫 flow-test,他就存了一個 log 檔叫做 zSUserszSwaynezSwszStmpzSflow-test.log 看不太懂齁~ 把 zS 換成 / 去掉就會變成 /User/wayne/ws/tmp/flow-test.log

max_header_tokens ( integer )

我們知道 Flow 他是透過 // @flow// @noflow 註解來決定是否為 Flow 檔案,進一步進行型別檢查。 但是 Flow 不可能無限的檢查下去,因此 Flow 有一個斷點機制 透過 max_header_tokens ,告訴 Flow 要往下檢查幾個註解

// ... 1
// ... 2
// ... 3
// ... 4
// ... 5
// ... 6
// ... 7
// ... 8
// ... 9
// ... 10
// @flow
const num: string = 123; // Flow 不會檢查這個檔案,因為註解已經超過 10 段了, Flow 程序已經判定他不是 Flow 檔案了

預設為 10

module.file_ext ( string )

預設情況下 Flow 會去偵測以下副檔名的檔案 .js, .jsx, .mjs, .cjs 還有 .json, 我們可以透過定義 module.file_ext 來覆蓋原先的設定

像是這樣

[options]
module.file_ext=.foo
module.file_ext=.bar

這樣設定之後 Flow 就只會檢查 .foo.bar 檔了 ( 原先的 .js, .jsx ... 就都不檢查了 )

Note: module.file_ext 是可以定義多行的!

module.ignore_non_literal_requires ( boolean )

設定為 true 的話 Flow 在檢查 require() 方法時會接受 string 以外的輸入

// @flow
const requireDir = './foo';
const foo = require('./foo'); // 會通過檢查
const bar = require(requireDir); // 若是 module.ignore_non_literal_require=true 的話會通過檢查

預設值為 false

module.name_mapper ( regex -> string )

指定一段正規表達式,當匹配到的時候會將匹配到的地方轉換為箭頭 -> 後方的字串。

像是這樣:

[options]
module.name_mapper='^img/\(.*\)$' -> '<PROJECT_ROOT>/src/img/\1'

以上面的規則來說會將開頭為 img 匹配為 專案目錄下的 <PROJECT_ROOT>/src/img 目錄 之後不管在任何目錄下想要引入 <PROJECTROOT>/src/img 底下的資源只要這樣就好了

const img = require('img/foo.jpg'); // 這樣就會匹配到 <PROJECT_ROOT>/src/img/foo.jpg 了

---

另外官網有給出一個範例是這樣的

[options]
module.name_mapper='^image![a-zA-Z0-9$_]+$' -> 'ImageStub'

接著再使用 require('image!foo.jpg') 會等同於使用 require('ImageStub') 這樣

恩... 這個我測試了很多次 都覺得範例中的正規表達式好像少了一個 . 再提個 ISSUE 去問一下吧!

最後再來給大家看一下 Vue 當中是如何使用這段的吧!!

[options]
module.name_mapper='^compiler/\(.*\)$' -> '<PROJECT_ROOT>/src/compiler/\1'
module.name_mapper='^core/\(.*\)$' -> '<PROJECT_ROOT>/src/core/\1'
module.name_mapper='^shared/\(.*\)$' -> '<PROJECT_ROOT>/src/shared/\1'
module.name_mapper='^web/\(.*\)$' -> '<PROJECT_ROOT>/src/platforms/web/\1'
module.name_mapper='^weex/\(.*\)$' -> '<PROJECT_ROOT>/src/platforms/weex/\1'
module.name_mapper='^server/\(.*\)$' -> '<PROJECT_ROOT>/src/server/\1'
module.name_mapper='^entries/\(.*\)$' -> '<PROJECT_ROOT>/src/entries/\1'
module.name_mapper='^sfc/\(.*\)$' -> '<PROJECT_ROOT>/src/sfc/\1'

永遠要記得 Flow 只是型別檢查,我們這邊的設定是型別會取用匹配檔案的而已,並不是真的引用到那個檔案, 設定了 Flow 的 module.name_mapper 之後,Webpack 之類的打包工具一樣要設定好才會是真的通哦!

module.name_mapper.extension ( string -> string )

指定副檔名匹配到另外指定的自串

這只是 module.name_mapper='^\(.*\)\.EXTENSION$' -> 'TEMPLATE' 的簡易寫法而已

使用範例:

[options]
module.name_mapper.extension='css' -> '<PROJECT_ROOT>/src/CSSFlowStub.js.flow'

這樣設定就會將所有副檔名為 .css 都匹配到 <PROJECT_ROOT>/src/CSSFlowStub.js.flow 這個檔案了

Note: module.name_mapper.extension 是可以定義多行的!

module.system ( node | haste )

用於解析 import 跟 require 語法的系統,haste 是用在 React Native 的。 預設是 node

module.system.node.main_field ( string )

預設情況下 Flow 在引入第三方套件時會去查看套件中的 package.jsonnamemain 欄位來決定實際引入的檔案。

但我們還是可以透過以下設定覆蓋:

[options]
module.system.node.main_field=foo
module.system.node.main_field=bar
module.system.node.main_field=baz

設定後 Flow 就會用這些指定的名稱去查看 package.json

{
"name": "kittens",
"main": "main.js",
"bar": "bar.js",
"baz": "baz.js"
}

以此案例來說,最終會引入 baz.js 作為 kittens 模組 Flow 型別的依據 ( 前提是 kittens 專案下有 baz.js 這個檔案 ) ( 再次碎碎念: Flow 只是型別不是實際引入 )

如果沒有設定 module.system.node.main_field 的話 Flow 會使用 "main" 欄位作為依據

接下來說一下筆者實際使用的心得與注意事項

  1. 沒有設定就不會讀取 以上面的使用案例來說 我們只有指定 foo, bar, baz 所以一般非 Flow 專案使用的 "main" 就不會讀取到了,這樣會導致無法使用非 Flow 專案的第三方套件,甚至連沒有特別設定的 Flow 第三方套件都不能使用了...

  2. 永遠要指定 "main" 如上所述,不指定 "main" 的話會導致其他 package.json 沒有設定我們自己指定欄位的都錯掉,也就是一般的第三方套件都會錯光光了!

  3. 先到的先用,找不到就往下找 聽著繞口,以上面使用的為例

    [options]
    module.system.node.main_field=foo
    module.system.node.main_field=bar
    module.system.node.main_field=baz

    如果引入的套件 package.json 中沒有定義 "foo",那就會往下使用 "bar",如果也沒有 "bar" 就會繼續往下引用到 "baz",以此類推,所以筆者多次提到要指定 "main",就是為了避免這種錯誤發生。最好事在最後一行定義 "main"

Note: module.system.node.main_field 是可以定義多行的! Todo: 需要提個 ISSUE 問問官方 感覺順序跟官方描述有點反過來了...

esproposal.class_instance_fields ( enable | ignore | warn )

設定為 warn 的話 Flow 會檢查是否在 class 中宣告實例成員 也可以設定為 ignore 叫 Flow 忽略不要檢查。

// @flow
class Welcome {
test = 123; // 若 esproposal.class_instance_fields=warn 會報錯。
}

預設是 enable,也就是允許使用的意思!

實測發現 esproposal 相關的設定在 Flow v1.135.0 版本之後就不再支援囉! 已經向社群提出 Issue 囉!

esproposal.class_static_fields ( enable | ignore | warn )

設定為 warn 的話 Flow 會檢查是否在 class 中使用 static 成員 也可以設定為 ignore 叫 Flow 忽略不要檢查。

// @flow
class Welcome {
static foo = {}; // 若 esproposal.class_static_fields=warn 會報錯。
}

預設是 enabel,也就是允許使用的意思!

實測發現 esproposal 相關的設定在 Flow v1.135.0 版本之後就不再支援囉! 已經向社群提出 Issue 囉!

esproposal.decorators ( ignore | warn )

設定為 ignore 的話 Flow 會忽略檢查 JavaScript 的 decorator ( decorator 可以參考這篇 )

// @flow
class Welcome {
@Decorator // 若 esproposal.decorators=ignore 的話不會報錯,設定為 warn 或不設定都會報錯
sayHi(): void {
console.log('Hello');
}
}

預設是 warn,當我們在使用 decorator 的時候 Flow 會報錯。

實測發現 esproposal 相關的設定在 Flow v1.135.0 版本之後就不再支援囉! 已經向社群提出 Issue 囉!

esproposal.export_star_as ( enable | warn | ignore )

設定為 enable 的話 Flow 會支援 export * as 這樣的語法 ( 參考 export ns from )

也可以設定為 ignore 叫 Flow 忽略不要檢查這個語法, 或是設定為 warn,讓 Flow 顯示警告訊息。

// @flow
// esproposal.export_star_as=warn 的話 Flow 會顯示警告訊息
export * as Mod form './export-something';

實測發現 esproposal 相關的設定在 Flow v1.135.0 版本之後就不再支援囉! 已經向社群提出 Issue 囉!

esproposal.optional_chaining ( enable | warn | ignore )

設定為 enable 的話 Flow 會支援 optional chaining 這樣的語法 ( 參考 Optional Chaining )

也可以設定為 ignore 叫 Flow 忽略不要檢查 設定為 warn 可以叫 Flow 顯示出警告訊息。

// @flow
type Shape = {
foo?: {
bar: number,
},
}
const obj: Shape = {
foo: {
bar: 123,
},
}
// esproposal.optional_chaining=enable 的話會解析成功,warn 的話會顯示警告訊息,ignore 會忽略不檢查
const num: vode | number = obj.foo?.bar;

需要提出個 ISSUE,看起來預設值並不是 warn,而是 ignore 或 enable 才對

esproposal.nullish_coalescing ( boolean )

設定為 enable 的話,Flow 會之支援 nullish coalescing 這樣的語法 ( 參考 Nullish Coalescing )

也可以設定為 ignore 叫 Flow 忽略不要檢查 設定為 warn 可以叫 Flow 顯示出警告訊息。 ( 目前實測有 bug ?? )

// @flow
const response = {
settings: {
animationDuration: 0,
}
};
// 如果 esproposal.nullish_coalescing 設定為 warn 應該要出現提醒訊息,只是實測沒有
const animationDuration = response.settings.animationDuration ?? 300;

實測發現 esproposal 相關的設定在 Flow v1.135.0 版本之後就不再支援囉! 已經向社群提出 Issue 囉!

可能也需要提出個 ISSUE,看起來就算設定為 warn 也不會正確的跳出提示