跳到主要內容

idx:存在性函數

·2 分鐘閱讀
Timothy Yung
Facebook 工程經理

在 Facebook,我們經常需要存取使用 GraphQL 擷取的資料結構中,深度巢狀的值。在存取這些深度巢狀值的過程中,一個或多個中間欄位通常是可為 null 的。這些中間欄位可能因為各種原因而為 null,從隱私權檢查失敗,到 null 碰巧是表示非致命錯誤最彈性的方式。

遺憾的是,目前存取這些深度巢狀的值既繁瑣又冗長。

props.user &&
props.user.friends &&
props.user.friends[0] &&
props.user.friends[0].friends;

一個 ECMAScript 提案,旨在引入存在性運算子,這將使此操作更加方便。但在該提案最終確定之前,我們希望有一個解決方案,可以改善我們的生活品質、維持現有的語言語意,並鼓勵使用 Flow 的型別安全。

我們提出了一個存在性函數,我們稱之為 idx

idx(props, _ => _.user.friends[0].friends);

此程式碼片段中的調用行為,與上述程式碼片段中的布林運算式類似,但重複性顯著降低。idx 函數正好接受兩個引數

  • 任何值,通常是您想要存取巢狀值的物件或陣列。
  • 一個函數,接收第一個引數並存取其上的巢狀值。

理論上,idx 函數將會嘗試捕捉因存取 null 或未定義屬性而導致的錯誤。如果捕捉到此類錯誤,它將傳回 null 或未定義。(您可以查看如何在 idx.js 中實作此功能。)

實際上,嘗試捕捉每個巢狀屬性存取都很慢,而且區分特定種類的 TypeError 很脆弱。為了應對這些缺點,我們建立了一個 Babel 外掛程式,將上述 idx 調用轉換為以下運算式

props.user == null
? props.user
: props.user.friends == null
? props.user.friends
: props.user.friends[0] == null
? props.user.friends[0]
: props.user.friends[0].friends;

最後,我們為 idx 新增了一個自訂 Flow 型別宣告,允許在第二個引數中的遍歷進行適當的型別檢查,同時允許在可為 null 的屬性上進行巢狀存取。

該函數、Babel 外掛程式和 Flow 宣告現在可在 GitHub 上取得。它們透過安裝 idxbabel-plugin-idx npm 套件,並將 “idx” 新增到您的 .babelrc 檔案中的外掛程式清單來使用。