Graphql 中的包装器类型是啥?

Posted

技术标签:

【中文标题】Graphql 中的包装器类型是啥?【英文标题】:What is a wrapper type in Graphql?Graphql 中的包装器类型是什么? 【发布时间】:2020-03-13 16:10:42 【问题描述】:

我正在学习 GraphQl 官方文档。

当我来到章节自省 link here

我遇到了一种叫做包装器类型的东西。

输入


  __type(name: "Droid") 
    name
    fields 
      name
      type 
        name
        kind
      
    
  

输出:


  "data": 
    "__type": 
      "name": "Droid",
      "fields": [
        
          "name": "id",
          "type": 
            "name": null,    # here 
            "kind": "NON_NULL"
          
        ,
        
          "name": "name",
          "type": 
            "name": null,    # here 
            "kind": "NON_NULL"
          
        ,
        
          "name": "friends",
          "type": 
            "name": null,    #  here 
            "kind": "LIST"
          
        ,
        
          "name": "friendsConnection",
          "type": 
            "name": null,       # here 
            "kind": "NON_NULL"
          
        ,
        
          "name": "appearsIn",
          "type": 
            "name": null,      # here 
            "kind": "NON_NULL"
          
        ,
        
          "name": "primaryFunction",
          "type": 
            "name": "String",     # normal here
            "kind": "SCALAR"
          
        
      ]
    
  

文章声称那些类型为的字段的名称为NULL,因为它是一种“包装器”类型的NON_NULL

谁能解释一下包装器类型到底是什么?最好提供一个示例或代码来解释为什么 primaryFunction 有名字而其他人没有。

【问题讨论】:

【参考方案1】:

来自spec:

到目前为止,所有类型都被假定为可为空和单数:例如标量字符串返回 null 或单数字符串。

一个 GraphQL 模式可以描述一个字段代表另一个类型的列表;出于这个原因提供了 List 类型,并包装了另一种类型。

同样,Non-Null 类型包装了另一种类型,并表示结果值永远不会为 null(并且错误不会导致 null 值)。

这两种类型被称为“包装类型”;非包装类型称为“命名类型”。包装类型具有底层命名类型,通过不断解包装类型直到找到命名类型来找到。

一个包装类型包装另一个类型,它本身也可能是一个包装类型。但是,当您“解包”每个包装类型时,最终您必须找到所有这些包装类型都与之关联的命名类型。换句话说,包装类型永远不能单独使用。包装类型始终只有一个与之关联的命名类型。

自省,要确定包裹类型是包裹什么类型,使用ofType字段:


  __schema 
    types 
      name
      ofType 
        name
      
    
  

您可以进一步为潜在的“展开”类型添加额外的级别:


  __schema 
    types 
      name
      ofType 
        name
        ofType 
          name
        
      
    
  

至于为什么内省没有显示这些类型的名称,这是因为规范明确禁止它。查看List 类型的部分:

列表表示 GraphQL 中的值序列。 List 类型是一个类型修饰符:它在 ofType 字段中包装了另一个类型实例,该字段定义了列表中每个项目的类型。

字段

kind 必须返回 __TypeKind.LIST。 ofType:任何类型。 所有其他字段必须返回 null。

【讨论】:

【参考方案2】:

这是我前几天完成的教程中的一些 sn-p。它表示用 GraphQLNonNull 运算符包装的类型(它用于服务器端):

const ContestStatusType = require('./contest-status')
const NameType = require('./name')

module.exports = new GraphQLObjectType(
  name: 'ContestType',
  fields: 
    id:  type: GraphQLID ,
    description:  type: GraphQLString ,
    status:  type: new GraphQLNonNull(ContestStatusType) ,
    createdAt:  type: new GraphQLNonNull(GraphQLString) ,
    createdBy:  type: new GraphQLNonNull(GraphQLString) ,
    names: 
      type: new GraphQLList(NameType),
      resolve(obj, args,  loaders, pgPool ) 
        return loaders.namesForContestIds.load(obj.id);
        return pgdb(pgPool).getNames(obj)
      
    
  
);

【讨论】:

以上是关于Graphql 中的包装器类型是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何解析 GraphQL 中的嵌套类型?

NodeJs 中的 GraphQl - 对象类型的解析器

使用 n-deep 包装器类型堆栈获取模式

将 ownProps 传递给 Apollo graphql 包装的组件

对象对象的 GraphQL 模式/解析器是啥样的?

在 graphql-yoga 中返回枚举的解析器函数是啥样的?