Union types
Union types are similar to interfaces however, while interfaces dictate fields that must be common to all implementations, unions do not. Unions only represent a selection of allowed types and make no requirements on those types. Hereβs a union, expressed in GraphQL Schema Definition Language (SDL):
union MediaItem = Audio | Video | Image
Whenever we return a MediaItem
in our schema, we might get an Audio
, a
Video
or an Image
. Note that members of a union type need to be concrete
object types; you cannot create a union type out of interfaces, other unions or
scalars.
A good use case for unions would be on a search field. For example:
searchMedia(term: "strawberry") { ... on Audio { duration } ... on Video { thumbnailUrl } ... on Image { src }}
Here, the searchMedia
field returns [MediaItem!]!
, a list where each member
is part of the MediaItem
union. So, for each member, we want to select different
fields depending on which kind of object that member is. We can do that by using
inline fragments.
Defining unions
In Strawberry there are two ways to define a union:
You can use the use the Union
type from the typing
module which will
autogenerate the type name from the names of the union members:
from typing import Unionimport strawberry
@strawberry.typeclass Audio: duration: int
@strawberry.typeclass Video: thumbnail_url: str
@strawberry.typeclass Image: src: str
@strawberry.typeclass Query: latest_media: Union[Audio, Video, Image]
union AudioVideoImage = Audio | Video | Image
type Query { latestMedia: AudioVideoImage!}
type Audio { duration: Int!}
type Video { thumbnailUrl: String!}
type Image { src: String!}
Or if you need to specify a name or a description for a union you can use the
strawberry.union
function:
import strawberry
@strawberry.typeclass Query: latest_media: strawberry.union("MediaItem", types=(Audio, Video, Image))
union MediaItem = Audio | Video | Image
type Query { latest_media: AudioVideoImage!}
type Audio { duration: Int!}
type Video { thumbnailUrl: String!}
type Image { src: String!}
Resolving a union
When a fieldβs return type is a union, GraphQL needs to know what specific
object type to use for the return value. In the example above, each MediaItem
must be categorized as an Audio
, Image
or Video
type. To do this you need
to always return an instance of an object type from your resolver:
from typing import Unionimport strawberry
@strawberry.typeclass Query: @strawberry.field def latest_media(self) -> Union[Audio, Video, Image]: return Video( thumbnail_url="https://i.ytimg.com/vi/dQw4w9WgXcQ/hq720.jpg", )