GraphQL —— 接口類型

在 GraphQL 中,接口(InterfaceTypeDefinition)也是一種命名字段集合,定義規則與對象類型極其類似,一樣支持 字段名、類型、參數 三要素。 與 OOP 概念相似,GraphQL 中的接口只是對資源的抽象描述,必須被其餘對象類型實現,才能正常使用。咱們來看個例子:git

interface NamedEntity {
  name: String
}

type User implements NamedEntity {
  id: ID!
  name: String
}
複製代碼

上例中,NamedEntity 即爲接口;User 是實現了該接口的對象類型。注意,實現類必須實現接口的全部字段,字段名、類型、參數都必須與接口匹配。 GraphQL 支持多繼承:github

interface NamedEntity {
  name: String
}

interface Node {
  id: ID!
}

'''
非法示例:
沒有實現Node接口的id字段
'''
type User implements NamedEntity & Node {
  name: String
}
複製代碼

那麼,在什麼場景下應該使用接口?咱們要理解,接口是對資源的抽象描述,不必定完備、詳盡,但每每能表述多類類似資源的共同特徵,因此若是服務中存在一些具有共性的類型,而用戶須要關注共同的這一部分,就應該使用接口。 好比,咱們有三種類型的商品:飲料、圖書、電器:bash

type Drinks {
  id: ID!
  name: String!
  price: Float!

  '''
  容量,單位爲ml
  '''
  capacity: Float!
}

type Book {
  id: ID!
  name: String!
  price: Float!

  '''
  做者
  '''
  author: [People]
  issn: String!
}

type ElectricalEquipment {
  id: ID!
  name: String!
  price: Float!

  '''
  生產商
  '''
  manufacturer: Company
}
複製代碼

上面三個商品對象有三個類似的屬性:idnameprice,是商品資源的不一樣類型。如今,咱們須要實現根據名稱搜索商品,若是接口功能,就必須使用近似的邏輯,在三種類型節點上,重複定義三次;若是將來咱們增長更多公共查詢邏輯,咱們又得把邏輯重複三遍,這顯然不是一個好的設計。這種狀況下就適合使用接口,將三個公共字段抽取出來,再以接口類型對外暴露商品的聚合查詢節點:ide

interface Item {
  id: ID!
  name: String!
  price: Float!
}

type Drinks implements Item{ ... }

type Book implements Item{ ... }

type ElectricalEquipment implements Item{ ... }

type Query {
  '''
  商品列表,支持按商品名查詢
  '''
  items(name: Sring): [Item]
}
複製代碼

而對於客戶端來講,針對接口節點的查詢,除了接口的屬性外,也支持查詢實現類的字段:函數

query {
  items(name: 'coka') {
    name
    ... on Drinks {
      capacity
    }
  }
}
複製代碼

代碼片斷 ... on Drinks { capacity },被稱爲 Inline Fragments。 針對這段查詢,引擎會幫助判斷若是解析結果爲 Drinks 類型,則返回 capacity 字段;若是是其餘類型的商品,則不作進一步處理,不會返回 capacity,也不報錯。有興趣的讀者,能夠到 GraphQL 接口示例代碼 看看。ui

注意,GraphQL 引擎沒有檢測類型的能力,開發者必須爲接口節點提供 resolveType 函數,以在運行時指定解析結果的類型!不然會報錯:spa

Abstract type NamedEntity must resolve to an Object type at runtime for field Query.users with value { id: 1, name: \"foo\", age: 1, type: \"User\" }, received \"undefined\". Either the NamedEntity type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function. 複製代碼
相關文章
相關標籤/搜索