async-graphql/docs/en/src/define_union.md

98 lines
1.9 KiB
Markdown
Raw Normal View History

2020-04-15 03:15:30 +00:00
# Union
2020-09-01 05:47:22 +00:00
The definition of a `Union` is similar to an `Interface`, **but with no fields allowed.**.
The implementation is quite similar for `Async-graphql`; from `Async-graphql`'s perspective, `Union` is a subset of `Interface`.
The following example modified the definition of `Interface` a little bit and removed fields.
```rust
use async_graphql::*;
struct Circle {
radius: f32,
}
#[Object]
impl Circle {
async fn area(&self) -> f32 {
std::f32::consts::PI * self.radius * self.radius
}
async fn scale(&self, s: f32) -> Shape {
Circle { radius: self.radius * s }.into()
}
}
struct Square {
width: f32,
}
#[Object]
impl Square {
async fn area(&self) -> f32 {
self.width * self.width
}
async fn scale(&self, s: f32) -> Shape {
Square { width: self.width * s }.into()
}
}
#[derive(Union)]
2020-05-11 04:39:43 +00:00
enum Shape {
Circle(Circle),
Square(Square),
}
```
2020-10-01 02:44:47 +00:00
## Flattening nested unions
A restriction in GraphQL is the inability to create a union type out of
other union types. All members must be concrete types. To support nested
unions, we can "flatten" members that are unions, bringing their members up
into the parent union. This is done by applying `#[item(flatten)]` on each
member we want to flatten.
```rust
#[derive(async_graphql::Union)]
pub enum TopLevelUnion {
A(A),
// Will fail to compile unless we flatten the union member
#[item(flatten)]
B(B),
}
#[derive(async_graphql::SimpleObject)]
pub struct A {
// ...
}
#[derive(async_graphql::Union)]
pub enum B {
C(C),
D(D),
}
#[derive(async_graphql::SimpleObject)]
pub struct C {
// ...
}
#[derive(async_graphql::SimpleObject)]
pub struct D {
// ...
}
```
The above example transforms the top-level union into this equivalent:
```rust
#[derive(async_graphql::Union)]
pub enum TopLevelUnion {
A(A),
C(C),
D(D),
}
```