为什么GraphQL'implements'需要复制字段,这是强制性的吗?如果是,根本原因是什么?

为什么GraphQL'implements'需要复制字段,这是强制性的吗?如果是,根本原因是什么?,graphql,graphql-js,Graphql,Graphql Js,为什么GraphQL实现了关键字需要复制字段,这是强制性的吗?如文件中的示例: enum Episode { NEWHOPE, EMPIRE, JEDI } interface Character { id: String name: String friends: [Character] appearsIn: [Episode] } type Human implements Character { id: String name: String friends

为什么GraphQL
实现了
关键字需要复制字段,这是强制性的吗?如文件中的示例:

enum Episode { NEWHOPE, EMPIRE, JEDI }

interface Character {
  id: String
  name: String
  friends: [Character]
  appearsIn: [Episode]
}

type Human implements Character {
  id: String
  name: String
  friends: [Character]
  appearsIn: [Episode]
  homePlanet: String
}

type Droid implements Character {
  id: String
  name: String
  friends: [Character]
  appearsIn: [Episode]
  primaryFunction: String
}
如果是,根本原因是什么


因为如果我必须复制,如果我改变,那么我需要到处改变…

是的,这是强制性的。如果有帮助的话,可以将其视为类似于Java类和接口。接口具有类型签名,但不能具有实现。它是在类中编写所有实现的,并且类型签名会被重复。这使您能够在类型签名中选择子类型或协变类型,因此它们可能不完全相同

现在假设您正在使用来自的JavaScript对象创建一个GraphQL模式。接口只是字段名和类型。对象类型定义本身具有“实现”或
resolve
resolveType
,以及其他使其成为可执行模式的属性

但是,您的示例使用的是模式语言,它根本没有“实现”。因此,它们几乎是彼此的精确重复。您不必每次都把它拼出来,您可以使用字符串插值来共享部分接口

const characterFields = `
  id: String
  name: String
  friends: [Character]
  appearsIn: [Episode]
`

const typeDefs = `
  interface Character {
    ${characterFields}
  }

  type Human Implements Character {
    ${characterFields}
    homePlanet: String
  }
`

编辑:与Java比较类似,字段的类型可能不完全相同。正如RomanHotsiy所指出的,您可以使类型不可为null,或者使用多态类型的子类型。

是的,根据当前的规则,这是强制性的:

对于接口中定义的每个字段,对象类型必须包含一个同名字段

const characterFields = `
  id: String
  name: String
  friends: [Character]
  appearsIn: [Episode]
`

const typeDefs = `
  interface Character {
    ${characterFields}
  }

  type Human Implements Character {
    ${characterFields}
    homePlanet: String
  }
`
它允许您在派生类型中更精确地指定字段类型。字段可以更改为非空或接口或联合的某些特定子类型。以你的例子来说,让我们假设人类只与其他人类交朋友,机器人也是如此。那么下面的模式是有效的

interface Character {
  id: String
  name: String
  friends: [Character]
  appearsIn: [Episode]
}

type Human implements Character {
  id: String
  name: String
  friends: [Human] # <- notice Human here
  appearsIn: [Episode]
  homePlanet: String
}

type Droid implements Character {
  id: String
  name: String
  friends: [Droid!]! # <- specified Droid here + added not null
  appearsIn: [Episode]
  primaryFunction: String
}
接口字符{
id:字符串
名称:String
朋友:[角色]
[插曲]
}
人字{
id:字符串
名称:String

朋友:[人类]#非常感谢您的回答和伟大的比较,但只能选择一个答案,组合将是最好的。@andy carlson拥有一个包含
字符
人类
公共字段的外部文件,然后添加到
…characterFields
等字段,这两者之间有什么区别?