如何在 GraphQL 类型中引用特定的 ENUM 值?

Posted

技术标签:

【中文标题】如何在 GraphQL 类型中引用特定的 ENUM 值?【英文标题】:How to reference a specific ENUM value in GraphQL type? 【发布时间】: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!

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

【问题讨论】:

你找到解决办法了吗? 【参考方案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 
        # ...
      
    
  

【讨论】:

以上是关于如何在 GraphQL 类型中引用特定的 ENUM 值?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 graphql-tools 使用或解析枚举类型?

GraphQL:如何处理在自己的类型定义中引用类型?

GraphQL & Mongoose Schema - 如何将一组 mongoose objectId 引用存储到另一种类型?

Python GraphQL 如何声明一个自引用的石墨烯对象类型

GraphQL 枚举联合解决方法?

无法在 GraphQL Schema 中嵌套类型