Union

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.


#![allow(unused)]
fn main() {
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)]
enum Shape {
    Circle(Circle),
    Square(Square),
}
}

Flattening nested unions

A restriction in GraphQL is the inability to create a union type out of other union types. All members must be Object. To support nested unions, we can "flatten" members that are unions, bringing their members up into the parent union. This is done by applying #[graphql(flatten)] on each member we want to flatten.


#![allow(unused)]
fn main() {
#[derive(async_graphql::Union)]
pub enum TopLevelUnion {
    A(A),

    // Will fail to compile unless we flatten the union member
    #[graphql(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:


#![allow(unused)]
fn main() {
#[derive(async_graphql::Union)]
pub enum TopLevelUnion {
    A(A),
    C(C),
    D(D),
}
}