摘要
在 Flow 0.28 之前,工會/交集類型的實作有嚴重的錯誤,而且是the root cause of a lot of weird behaviors,您過去可能在 Flow 中遇到過。這些錯誤現已在0.28 中的 diff landing中得到解決。
在對類型系統實作的棘手部分進行重大改寫後,您可能會預期有一段時間的調整:您可能會遇到一些我們會盡快解決的故障,而且您可能會遇到一些不熟悉的錯誤訊息。
新的錯誤訊息
<error location> Could not decide which case to select
<location of union/intersection type>
Case 1 may work:
<location of 1st case of union/intersection type>
But if it doesn't, case 2 looks promising too:
<location of 2nd case of union/intersection type>
Please provide additional annotation(s) to determine whether case 1 works
(or consider merging it with case 2):
<location to annotate>
<location to annotate>
...
這表示在 <error location> 中,Flow 需要做出選擇:<location of union/intersection type> 中的工會/交集類型的其中一個成員必須套用,但 Flow 無法根據可用的資訊安全地選擇。特別是,它無法在案例 1 和 2 之間做出決定,因此 Flow 會列出一堆註解,這些註解有助於它區分這兩個案例。
必要的動作
您可以透過兩種方式修正錯誤
- 實際前往並註解列出的位置。這應該是迄今最常見的修正方式。
- 發現案例 1 和 2 之間存在真正的非預期歧義,並改寫聯集類型中的兩個案例以移除歧義。當這種情況發生時,通常會修正大量的錯誤。
不過,還有兩種可能性
- 沒有真正的歧義,而 Flow 過於保守/愚蠢。在這種情況下,請繼續進行註解,並在 GitHub 上提交問題。我們計畫進行大量的短期後續工作,以自動消除更多案例的歧義,因此隨著時間推移,您應該會看到較少的 (3)。
- 您不知道發生了什麼事。指出的案例沒有道理。它們與您在
<error location>中的內容不符。希望您不會太常遇到 (4),但如果您遇到,請提交問題,因為這表示實作中仍有潛在的錯誤。
如果您在 GitHub 上提交問題,請包含用於重現問題的程式碼。您可以使用 試試 Flow 輕鬆分享您的重現案例。
如果您對這些新錯誤訊息的來龍去脈感到好奇,以下是「聯集的命運」diff 的提交訊息摘錄
問題
Flow 的推論引擎旨在隨著加入約束而找出更多錯誤...但它並非設計為回溯。不幸的是,檢查表達式的類型是否符合聯集類型確實需要回溯:如果聯集的某個分支無法解決,則必須嘗試下一個分支,依此類推。(對於涉及交集類型的檢查也是如此。)
情況會因表達式的類型在檢查時可能尚未完全已知而變得更加複雜,因此現在看起來有希望的分支後來可能會變成不正確。
解決方案
基本概念是延遲嘗試分支,直到我們可以決定分支是否會在沒有進一步資訊的情況下確定失敗或成功。如果嘗試分支導致失敗,我們可以繼續下一個分支,而不需要回溯。如果一個分支成功了,我們就完成了。最後一種情況是分支看起來很有希望,但我們無法在不增加約束的情況下確定:在這種情況下,我們嘗試其他分支,並且在遇到歧義時放棄...請求額外的註解來決定選擇哪個分支。總的來說,這意味著(1)我們永遠不會承諾可能被證明是不正確的分支,並且(2)始終可以在有足夠註解的情況下選擇正確的分支(如果存在)。