Please refer to this example.只有在承諾鏈:
function f(a ?: Array<string>) {
a = a || [];
a.map // Here it is ok
return Promise.resolve()
.then(() => a.map) // THROWS, WHY?
}
Please refer to this example.只有在承諾鏈:
function f(a ?: Array<string>) {
a = a || [];
a.map // Here it is ok
return Promise.resolve()
.then(() => a.map) // THROWS, WHY?
}
Flow的類型細化是保守的。這意味着當它不能確定他們將持有時,它會積極地進行。
在這種情況下,Flow會看到a
已重新分配,因此它不得爲null
/undefined
。然而,它並沒有做分析知道是總是將會是null
/undefined
- 就其所知,稍後的一些分配可能會將其重新分配給null
/undefined
。
它也不知道什麼時候回調傳遞給.then
會被調用。所以,它保守地使提煉無效。
請注意,此問題不是特定於Promise
s。每當一個非const變量應用了一個優化時它就會發生,並且稍後將用於閉包。在關閉內部,細化將被丟棄。
簡單的解決方法是使用const
。然後,流量知道被應用於任何類型的細化將永遠持有,因爲變量不能被重新分配:
function f(a_ ?: Array<string>) {
const a = a_ || [];
a.map // Here it is ok
return Promise.resolve()
.then(() => a.map) // THROWS, WHY?
}
那是因爲在你的函數定義「屬性不能在可能未定義的訪問」您有:
function f(a ?: Array<string>) {
這意味着a
的類型是字符串數組,但它是可空的(?:
)。它的值可以爲null(或未定義)。
雖然從您的代碼很明顯,a
如果它的null
(或未定義)被空數組重寫。但是它的類型仍然是一個可空的字符串數組。
當編譯器試圖編譯這一行:
.then(() => a.map) // THROWS, WHY?
它認爲a
可能爲空(或undefined),並以一個錯誤如此抱怨。
如果您刪除函數參數類型中的問號?
,編譯器知道a
不能爲空,因此它的工作原理!
PS:如果需要,您可以將a = a || [];
移動到調用函數f
的函數中。
不; Flow非常聰明,知道'a = a || [];'將'a'的類型改進爲不再包含'null'。這就是爲什麼第一個'a.map'很好。問題是這個流程分析不包括閉包。 – SLaks
可能是因爲它不適用的拉姆達內部細化。 – SLaks
@SLaks它的確如此。請檢查我的答案。 –