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 函数,以在运行时指定解析结果的类型!不然会报错:设计

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.
相关文章
相关标签/搜索