GraphQL Union Types — Polymorphic Responses Without Shared Fields
In this tutorial, you will learn about Graphql Union Types. We cover key concepts, practical examples, and best practices to help you master this topic.
GraphQL union types allow a field to return one of several different object types, enabling polymorphic responses where the returned types may have no fields in common.
What You'll Learn
- Defining union types
- Querying unions with inline fragments
- Implementing __resolveType for unions
Why It Matters
Unions enable flexible search results, notification systems, and event feeds where different types of data can appear in the same field.
Code Examples
# Union type definitions
union SearchResult = User | Post | Comment | Product
union Notification = EmailNotification | PushNotification | SMSNotification
union MediaItem = Image | Video | Audio | Document
type Query {
search(term: String!): [SearchResult!]!
notifications(userId: ID!): [Notification!]!
mediaLibrary: [MediaItem!]!
}
# Querying unions with inline fragments
query {
search(term: "graphql") {
... on User {
name
email
}
... on Post {
title
content
author { name }
}
... on Comment {
text
post { title }
}
... on Product {
name
price
}
}
}
// Union resolver with __resolveType
const typeDefs = `
union SearchResult = User | Post | Comment
type User {
id: ID!
name: String!
email: String!
}
type Post {
id: ID!
title: String!
content: String!
}
type Comment {
id: ID!
text: String!
}
`;
const resolvers = {
SearchResult: {
__resolveType(parent) {
if (parent.name) return 'User';
if (parent.title) return 'Post';
if (parent.text) return 'Comment';
return null; // GraphQL Error
}
}
};
# Python union type with Strawberry
import strawberry
from typing import Union
@strawberry.type
class User:
id: strawberry.ID
name: str
@strawberry.type
class Post:
id: strawberry.ID
title: str
SearchResult = strawberry.union(
"SearchResult",
(User, Post)
)
@strawberry.type
class Query:
@strawberry.field
def search(self, term: str) -> list[SearchResult]:
results = []
results.extend(search_users(term))
results.extend(search_posts(term))
return results
Common Mistakes
1. Using Unions When Interfaces Would Work Better
If types share common fields, use interfaces instead of unions.
2. Not Handling Unknown Types in __resolveType
Return null for unknown types to trigger clear GraphQL errors.
3. Forgetting That Unions Cannot Have Fields
Unions are just lists of possible types. They do not declare any fields.
4. Creating Overly Large Unions
Keep unions focused. A SearchResult with 20 types is hard to query.
5. Not Using Descriptive Union Names
Name unions by their purpose: SearchResult, Notification, MediaItem.
Practice Questions
- How do you define a union type?
- How do union types differ from interface types?
- How do you query type-specific fields on a union?
- What does __resolveType return for unions?
- Can a union include types from different services?
Answers:
- With the union keyword: union SearchResult = Type1 | Type2.
- Unions have no shared fields; interfaces define common fields.
- Use inline fragments with ... on TypeName.
- The name of the concrete object type as a string.
- Yes, in federated graphs, unions can span multiple services.
Challenge: Design a union type for a social media feed that can return Post, Image, Video, SharedLink, and Poll types. Implement __resolveType and write complex queries using inline fragments.
FAQ
Mini Project
Build a feed system with a FeedItem union type that can return Post, Ad, Suggestion, Activity, and Announcement types. Implement the resolver with __resolveType, write queries that display each type differently, and add a new type to the union.
What's Next
Learn about input types for structured mutation arguments, then explore arguments deep dive for field arguments.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro