【问题标题】:How to reference a specific ENUM value in GraphQL type?如何在 GraphQL 类型中引用特定的 ENUM 值?
【发布时间】:2017-11-11 13:11:34
【问题描述】:

我有以下架构:

enum PaymentTypeName {
  PAYMENT_CARD
  PAYMENT_CARD_TOKEN
}

interface Payment {
  id: ID!
  type: PaymentTypeName!
}

type PaymentCardPayment implements Payment {
  id: ID!
  type: PaymentTypeName!
  card: PaymentCard!
}

type PaymentCardTokenPayment implements Payment {
  id: ID!
  type: PaymentTypeName!
  card: PaymentCard!
}

PaymentPaymentCardPaymentPaymentCardTokenPayment 时,由type 的值决定,即为PAYMENT_CARDPAYMENT_CARD_TOKEN

如何在界面中表示PaymentCardPayment/PaymentCardTokenPayment 继承了PaymentTypeName 的特定值?

我尝试了以下各种组合:

type PaymentCardPayment implements Payment {
  id: ID!
  type: PaymentTypeName.PAYMENT_CARD!
  card: PaymentCard!
}

和:

type PaymentCardPayment implements Payment {
  id: ID!
  type: PaymentTypeName[PAYMENT_CARD]!
  card: PaymentCard!
}

但所有这些都提示语法错误,我无法找到相关文档。

【问题讨论】:

  • 你找到解决办法了吗?

标签: graphql graphql-js


【解决方案1】:

您正试图在您的类型架构中声明字段 value,这不是架构的用途。你应该只在你的模式中声明你的字段type,在这种情况下它只是type: PaymentTypeName。您在第一个代码块中已正确。

您的PaymentCardPaymenttype 解析器函数应返回枚举的值,在您的情况下为PAYMENT_CARD

您的PaymentCardTokenPaymenttype 解析器函数应返回PAYMENT_CARD_TOKEN 的值。

【讨论】:

  • 我不同意。 ENUM 是一个特例。 PaymentType 上下文 type 可以继承任何 PaymentTypeName 值是有道理的。但是,在 PaymentCardPayment 的上下文中,说该值是 ENUM 值中的一个是误导性的;它不是。它是一个常量值,它是PaymentTypeName 的子集。
  • 必须同意,细化子集将始终是来自ENUM 的静态值,接口保证是有意义的,并且可能是ENUM 在不使用时使用的常见方式之一用于通过输入类型进行过滤。
  • 那么您找到解决方案了吗?
【解决方案2】:

使用默认值对你有用吗?

type PaymentCardPayment implements Payment {
  id: ID!
  type: PaymentTypeName! = PAYMENT_CARD
  card: PaymentCard!
}  

它不会阻止您覆盖该值,但至少应该正确设置它。

【讨论】:

  • 这会很棒。但我得到一个语法错误 - 你确定这有效吗?
【解决方案3】:

GraphQL 不支持您尝试执行的操作。如果一个字段的类型被声明为PaymentTypeName,并且PAYMENT_CARDPAYMENT_CARD_TOKEN 都是PaymentTypeName 的有效值,那么它们也必须是该字段的有效值。无法获取现有类型(无论是枚举、标量还是对象类型)并有条件地从该类型已定义的可能值集中创建可能值的子集。

也就是说,如果PaymentCardPayment.type 将始终解析为PAYMENT_CARD 并且PaymentCardTokenPayment.type 将始终解析为PAYMENT_CARD_TOKEN,那么在这里使用枚举根本没有意义。实际上,在这种特定情况下,我们可以完全省略 type 字段。毕竟,在这种情况下,该字段的唯一目的是允许客户端区分Payment 可能解析为的可能类型。但是,GraphQL 已经为我们提供了一个 __typename 字段,它通过解析为已解析类型的名称来做到这一点。

所以在这个特定的例子中,这样做就足够了:

interface Payment {
  id: ID!
}

type PaymentCardPayment implements Payment {
  id: ID!
  card: PaymentCard!
}

type PaymentCardTokenPayment implements Payment {
  id: ID!
  card: PaymentCard!
}

并像这样查询类型为Payment的字段:

{
  payments {
    id
    __typename
    ... on PaymentCardPayment {
      card {
        # ...
      }
    }
    ... on PaymentCardTokenPayment {
      card {
        # ...
      }
    }
  }
}

【讨论】:

    猜你喜欢
    • 2021-08-31
    • 2017-04-12
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    • 2022-08-17
    • 2021-12-03
    • 2019-12-06
    相关资源
    最近更新 更多