Bir*_*sky 6 algebraic-data-types graphql graphql-js
有没有一种技术可以让我在GraphQL中这样声明ADT?
// TypeScript
type SomeAlgebraicDataType =
| { state: 'A', subState1: string }
| { state: 'B', subState2: string, subState3: number }
| { state: 'C', subState4: string, subState5: string, subState6: number }
Run Code Online (Sandbox Code Playgroud)
注意如何基于state鉴别符来推断结构的其余部分。
下面是一些伪造的代码,说明了这个想法:
union AlgebraicDataType = StateA | StateB | StateC
type StateA {state: StateDiscriminator.A, subState1: String }
type StateB {state: StateDiscriminator.B, subState2: String, subState3: Int }
type StateC {state: StateDiscriminator.C, subState4: String, subState5: String, subState6: Int}
enum StateDiscriminator { A B C }
Run Code Online (Sandbox Code Playgroud)
根据规范:
GraphQL 联合表示一个对象,可以是 GraphQL 对象类型列表之一,但不提供这些类型之间的保证字段。它们与接口的不同之处还在于,对象类型声明它们实现的接口,但不知道哪些联合包含它们。
联合(和接口)在规范中被称为抽象类型,因为返回联合的字段的具体(即实际)类型直到运行时才知道。然而,联合也符合代数类型的一般定义,因为它们实际上是两个或多个对象类型的总和。
问题中的伪代码与工作示例相距不远:
union AlgebraicDataType = StateA | StateB | StateC
type StateA {state: StateDiscriminator, subState1: String }
type StateB {state: StateDiscriminator, subState2: String, subState3: Int }
type StateC {state: StateDiscriminator, subState4: String, subState5: String, subState6: Int}
enum StateDiscriminator { A B C }
Run Code Online (Sandbox Code Playgroud)
主要区别在于,当我们使用 SDL 定义模式时,我们必须指定如何与类型定义分开解析 Union。如果您使用apollo-serveror makeExecutableSchemafrom graphql-tools,我们会将此逻辑指定为解析器映射的一部分:
const resolvers = {
AlgebraicDataType: {
__resolveType: (obj) => {
switch (obj.state) {
case 'A': return 'StateA'
case 'B': return 'StateB'
case 'C': return 'StateC'
default: {
throw new TypeError(
`Unknown state for AlgebraicDataType: ${obj.state}`
)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您使用的是普通 GraphQL.js,则会将相同的函数作为参数提供给 Union 的构造函数resolveType。
还值得注意的是,如果resolveType未提供该函数,默认情况下 GraphQL 将查找__typename在所提供的对象上命名的属性并使用它来解析类型。因此,只要您在解析器中返回具有该属性的对象,就可以完全省略该函数。
| 归档时间: |
|
| 查看次数: |
300 次 |
| 最近记录: |