Schema 和类型

在本页,你将学到关于 GraphQL 类型系统中所有你需要了解的知识,以及类型系统如何描述可以查询的数据。因为 GraphQL 可以运行在任何后端框架或者编程语言之上,我们将摒除实现上的细节而仅仅专注于其概念。

接口(Interfaces)

跟许多类型系统一样,GraphQL 支持接口。一个接口是一个抽象类型,它包含某些字段,而对象类型必须包含这些字段,才能算实现了这个接口。

例如,你可以用一个 Character 接口用以表示《星球大战》三部曲中的任何角色:

  1. interface Character {
  2. id: ID!
  3. name: String!
  4. friends: [Character]
  5. appearsIn: [Episode]!
  6. }

这意味着任何实现Character 的类型都要具有这些字段,并有对应参数和返回类型。

例如,这里有一些可能实现了 Character 的类型:

  1. type Human implements Character {
  2. id: ID!
  3. name: String!
  4. friends: [Character]
  5. appearsIn: [Episode]!
  6. starships: [Starship]
  7. totalCredits: Int
  8. }
  9. type Droid implements Character {
  10. id: ID!
  11. name: String!
  12. friends: [Character]
  13. appearsIn: [Episode]!
  14. primaryFunction: String
  15. }

可见这两个类型都具备 Character 接口的所有字段,但也引入了其他的字段 totalCreditsstarshipsprimaryFunction,这都属于特定的类型的角色。

当你要返回一个对象或者一组对象,特别是一组不同的类型时,接口就显得特别有用。

注意下面例子的查询会产生错误:

  1. # { "graphiql": true, "variables": { "ep": "JEDI" } }
  2. query HeroForEpisode($ep: Episode!) {
  3. hero(episode: $ep) {
  4. name
  5. primaryFunction
  6. }
  7. }

hero 字段返回 Character 类型,取决于 episode 参数,它可能是 Human 或者 Droid 类型。上面的查询中,你只能查询 Character 接口中存在的字段,而其中并不包含 primaryFunction

如果要查询一个只存在于特定对象类型上的字段,你需要使用内联片段:

  1. # { "graphiql": true, "variables": { "ep": "JEDI" } }
  2. query HeroForEpisode($ep: Episode!) {
  3. hero(episode: $ep) {
  4. name
  5. ... on Droid {
  6. primaryFunction
  7. }
  8. }
  9. }

你可以在查询指南的 内联片段 章节了解更多相关信息。