透過使用類型系統,可以預先判斷 GraphQL 查詢是否有效。這讓伺服器和用戶端能在建立無效查詢時有效地通知開發人員,而無需依賴執行時期檢查。
對於我們的 Star Wars 範例,檔案 starWarsValidation-test.ts 包含多個查詢,展示各種無效情況,而且是一個可以執行以測試參考實作驗證器的測試檔案。
首先,我們來看看一個複雜的有效查詢。這是一個巢狀查詢,類似於前一節的範例,但將重複的欄位分解成一個片段
而且這個查詢是有效的。我們來看看一些無效查詢...
片段不能參照自己或建立循環,因為這可能會導致無界結果!以下是上面相同的查詢,但沒有明確的三層巢狀
當我們查詢欄位時,我們必須查詢給定類型上存在的欄位。因此,由於 hero
會傳回 Character
,我們必須查詢 Character
上的欄位。該類型沒有 favoriteSpaceship
欄位,所以這個查詢是無效的
每當我們查詢欄位,而且它傳回的不是純量或列舉時,我們需要指定要從欄位取得哪些資料。Hero 傳回 Character
,而且我們已經在上面請求 name
和 appearsIn
等欄位;如果我們省略它,查詢將會無效
類似地,如果一個欄位是純量,那麼查詢它額外的欄位沒有意義,這樣做會使查詢無效
前面提到,查詢只能查詢所討論類型上的欄位;當我們查詢會傳回 Character
的 hero
時,我們只能查詢 Character
上存在的欄位。但如果我們想要查詢 R2-D2 的主要功能,該怎麼辦?
這個查詢無效,因為 primaryFunction
不是 Character
上的欄位。我們想要一種方法來表示,如果 Character
是 Droid
,我們希望擷取 primaryFunction
,否則忽略該欄位。我們可以使用前面介紹的片段來執行此操作。透過設定在 Droid
上定義的片段並將其包含在內,我們確保只在定義 primaryFunction
的地方查詢它。
這個查詢有效,但有點冗長;當我們多次使用命名片段時,命名片段在上面很有用,但我們只使用這個片段一次。我們可以使用內嵌片段,而不是使用命名片段;這仍然允許我們指出我們正在查詢的類型,但不需要命名一個單獨的片段
這只是驗證系統的皮毛而已;有許多驗證規則可用來確保 GraphQL 查詢在語意上是有意義的。規範在「驗證」部分中更詳細地說明了這個主題,而 GraphQL.js 中的 驗證 目錄包含實作規範相容 GraphQL 驗證器的程式碼。