【问题标题】:graphql, union scalar type?graphql,联合标量类型?
【发布时间】:2018-09-28 13:18:55
【问题描述】:

payload 字段可以是 IntString 标量类型。 当我把它写成联合类型时:

const schema = `
  input QuickReply {
    content_type: String
    title: String
    payload: Int | String
    image_url: String
  }
`

我遇到了一个错误:

GraphQLError: Syntax Error GraphQL request (45:18) Expected Name, found |

    44:     title: String
    45:     payload: Int | String
                         ^
    46:     image_url: String

看来GraphQL 不支持联合标量类型。

那么,我该如何解决这种情况呢?

【问题讨论】:

    标签: graphql graphql-js


    【解决方案1】:

    标量不能用作联合的一部分,因为根据规范,联合专门“表示可能是 GraphQL 对象类型列表之一的对象”。相反,您可以使用自定义标量。例如:

    const MAX_INT = 2147483647
    const MIN_INT = -2147483648
    const coerceIntString = (value) => {
      if (Array.isArray(value)) {
        throw new TypeError(`IntString cannot represent an array value: [${String(value)}]`)
      }
      if (Number.isInteger(value)) {
        if (value < MIN_INT || value > MAX_INT) {
          throw new TypeError(`Value is integer but outside of valid range for 32-bit signed integer: ${String(value)}`)
        }
        return value
      }
      return String(value)
    }
    const IntString = new GraphQLScalarType({
      name: 'IntString',
      serialize: coerceIntString,
      parseValue: coerceIntString,
      parseLiteral(ast) {
        if (ast.kind === Kind.INT) {
          return coerceIntString(parseInt(ast.value, 10))
        }
        if (ast.kind === Kind.STRING) {
          return ast.value
        }
        return undefined
      }
    })
    

    此代码有效地结合了 Int 和 String 类型的行为,同时仍然强制 32 位有符号整数的范围。但是,您可以拥有任何类型的强制行为。查看the source code 了解内置标量如何工作,或查看this article 了解有关自定义标量如何工作的更多详细信息。

    请注意,如果您尝试为 output 字段返回多个标量之一,则可以使用 parent 类型的联合来获得类似的结果.例如,这是不可能的:

    type Post {
      content: String | Int
    }
    

    但您可以执行以下操作:

    type PostString {
      content: String
    }
    
    type PostInt {
      content: Int
    }
    
    union Post = PostString | PostInt
    

    【讨论】:

    • 超级有趣的答案!!!我在其他任何地方都找不到这样一个相关的例子......
    • 这听起来像是混合多个标量的好解决方案。在我的例子中,有一个任务的响应,它可能是标量(Int,String)或对象类型。我可以使用标量 JSON 代替对象类型,但 JSON 不验证内部字段,并且不能保证它们在响应中,而不是一个选项。所以我遇到了同样的问题,但似乎这个解决方案不适用于:union = String | Int | MyTypeOne | MyTypeTwo ... MyTypeTen。有什么建议吗?
    • @Mihail 除了使用 JSON 标量,您仍然可以创建一个自定义标量,其中包含特定于您的用例的验证。除此之外,如果您将其用于输出类型,您可以如上所述为父类型使用联合。
    猜你喜欢
    • 2019-07-01
    • 2017-12-30
    • 2018-03-28
    • 2019-06-30
    • 2020-02-09
    • 2021-04-01
    • 2018-10-22
    • 2021-03-17
    相关资源
    最近更新 更多