通过使用类型系统,可以预先确定 GraphQL 查询是否有效。这允许服务器和客户端在创建无效查询时有效地通知开发人员,而无需依赖运行时检查。
对于我们的星球大战示例,文件 starWarsValidation-test.ts 包含许多演示各种无效性的查询,并且是一个可以运行以测试参考实现验证器的测试文件。
首先,让我们来看一个复杂的有效查询。这是一个嵌套查询,类似于上一节中的示例,但重复的字段被分解成一个片段
这个查询是有效的。让我们看看一些无效的查询...
片段不能引用自身或创建循环,因为这会导致无界结果!以下是上面相同的查询,但没有显式的三级嵌套
当我们查询字段时,我们必须查询给定类型上存在的字段。因此,由于hero
返回一个Character
,我们必须查询Character
上的字段。该类型没有favoriteSpaceship
字段,因此此查询无效
无论何时我们查询一个字段,并且它返回的内容不是标量或枚举,我们需要指定要从该字段获取哪些数据。Hero 返回一个Character
,我们一直在请求它上面的字段,例如name
和appearsIn
;如果我们省略它,查询将无效
类似地,如果一个字段是标量,那么查询它上面的附加字段就没有意义,这样做会使查询无效
之前已经提到,查询只能查询相关类型上的字段;当我们查询返回Character
的hero
时,我们只能查询Character
上存在的字段。但是,如果我们想查询 R2-D2 的主要功能,该怎么办?
该查询无效,因为primaryFunction
不是Character
上的字段。我们希望有一种方法来表明我们希望获取primaryFunction
(如果Character
是Droid
),否则忽略该字段。我们可以使用之前介绍的片段来做到这一点。通过设置在Droid
上定义的片段并包含它,我们确保只在定义了primaryFunction
的地方查询它。
此查询有效,但有点冗长;当我们多次使用命名片段时,它们在上面很有价值,但我们只使用它一次。与其使用命名片段,我们可以使用内联片段;这仍然允许我们指示我们正在查询的类型,但无需命名单独的片段
这只是验证系统表面的一个部分;存在许多验证规则来确保 GraphQL 查询在语义上是有意义的。规范在“验证”部分更详细地介绍了此主题,并且 validation GraphQL.js 中的目录包含实现符合规范的 GraphQL 验证器的代码。