0
0
GraphQLquery~15 mins

Union types in GraphQL - Deep Dive

Choose your learning style9 modes available
Overview - Union types
What is it?
Union types in GraphQL allow a field to return one of several different object types. Instead of being limited to a single type, a union type lets you specify multiple possible types that the field can resolve to. This helps when a query might return different shapes of data depending on the situation.
Why it matters
Without union types, you would need to create separate fields or complex structures to handle different possible return types, making your API harder to use and maintain. Union types simplify queries and responses by clearly expressing that a field can have multiple possible types, improving flexibility and clarity for clients.
Where it fits
Before learning union types, you should understand basic GraphQL schema definitions, object types, and how queries work. After mastering union types, you can explore interfaces in GraphQL, which are similar but have different use cases and rules.
Mental Model
Core Idea
A union type is like a choice box that lets a field return one of several different object types, making the API flexible and expressive.
Think of it like...
Imagine a vending machine that can give you either a soda, a snack, or a sandwich depending on what you select. The vending machine is the field, and the possible items it can give are the union types.
Field
  │
  ├─> Type A
  ├─> Type B
  └─> Type C

This shows a field that can return either Type A, Type B, or Type C.
Build-Up - 7 Steps
1
FoundationBasic GraphQL Object Types
🤔
Concept: Understanding how to define simple object types in GraphQL.
In GraphQL, you define object types to describe the shape of data. For example: type Book { title: String author: String } type Movie { title: String director: String } These types describe what fields are available and their data types.
Result
You can query for books or movies and get their respective fields.
Knowing how to create object types is essential because union types combine multiple object types.
2
FoundationGraphQL Queries and Responses
🤔
Concept: How queries request data and how responses match the requested shape.
A query asks for specific fields from a type. For example: query { book { title author } } The response matches the shape: { "book": { "title": "1984", "author": "George Orwell" } } This shows how the client gets exactly what it asks for.
Result
Clients receive data shaped exactly as requested.
Understanding queries and responses helps grasp why union types need special handling to know which type was returned.
3
IntermediateDefining Union Types in Schema
🤔Before reading on: do you think union types allow fields to return multiple types at once or just one type at a time? Commit to your answer.
Concept: Union types let a field return one of several object types, but only one at a time.
You define a union type by listing possible object types: union SearchResult = Book | Movie Then a field can return SearchResult: type Query { search(text: String): SearchResult } This means the search field can return either a Book or a Movie, but not both simultaneously.
Result
The schema clearly states the possible return types for a field.
Knowing that union types represent one of many types, not multiple at once, clarifies how to handle responses.
4
IntermediateQuerying Union Types with Inline Fragments
🤔Before reading on: do you think you can query fields directly on a union type without specifying the concrete type? Commit to your answer.
Concept: To get fields from a union type, you use inline fragments to specify which type's fields you want.
Since a union can be one of many types, you must tell GraphQL which fields to fetch for each type: query { search(text: "1984") { ... on Book { title author } ... on Movie { title director } } } This way, the response includes fields based on the actual type returned.
Result
The query returns data with fields specific to the actual type of the result.
Understanding inline fragments is key to working with union types because it lets you safely access type-specific fields.
5
IntermediateResolving Union Types on the Server
🤔
Concept: The server must decide which concrete type to return for a union field and inform GraphQL accordingly.
When the server resolves a union field, it returns an object matching one of the union's types. It also provides a __typename field internally so GraphQL knows which type it is. For example, if search returns a Book, the server returns the Book object and GraphQL uses __typename to match the inline fragment.
Result
Clients receive the correct type data and can handle it properly.
Knowing the server's role in resolving union types helps understand how GraphQL delivers flexible data safely.
6
AdvancedUnion Types vs Interfaces in GraphQL
🤔Before reading on: do you think union types and interfaces are the same or have important differences? Commit to your answer.
Concept: Union types and interfaces both allow multiple types, but interfaces require shared fields while unions do not.
Interfaces define a set of fields that all implementing types must have: interface Media { title: String } type Book implements Media { title: String author: String } type Movie implements Media { title: String director: String } Union types just list possible types without requiring shared fields. This means unions are more flexible but less strict.
Result
You understand when to use unions (different types without common fields) versus interfaces (types sharing fields).
Recognizing the difference guides better schema design and clearer API contracts.
7
ExpertPerformance and Type Safety Considerations
🤔Before reading on: do you think using many union types can impact query performance or type safety? Commit to your answer.
Concept: Using union types extensively can affect query complexity and client type safety, requiring careful schema design and tooling support.
Because clients must use inline fragments for unions, queries can become verbose and complex. Also, some client tools may struggle with type inference for unions, making development harder. On the server, resolving unions requires extra logic to identify types correctly. Balancing flexibility with simplicity is key in production.
Result
You appreciate the tradeoffs of union types in large systems and the need for good tooling.
Understanding these tradeoffs helps avoid overusing unions and encourages thoughtful API design.
Under the Hood
Internally, GraphQL uses the __typename field to track which concrete type a union field resolves to. When a query with inline fragments runs, GraphQL checks __typename to select the matching fragment and returns only those fields. The server resolver returns an object with a type identifier so GraphQL can do this matching.
Why designed this way?
Union types were designed to allow flexible return types without forcing shared fields, unlike interfaces. This design lets APIs express diverse data shapes cleanly. The __typename mechanism ensures type safety and correct field resolution at runtime, balancing flexibility with predictable behavior.
Query Field
   │
   ▼
Resolver returns object with __typename
   │
   ▼
GraphQL runtime checks __typename
   │
   ├─> Matches inline fragment for Type A
   ├─> Matches inline fragment for Type B
   └─> Matches inline fragment for Type C
   │
   ▼
Returns fields for matched type only
Myth Busters - 4 Common Misconceptions
Quick: Can a union type field return multiple types at the same time? Commit to yes or no.
Common Belief:A union type field can return multiple types simultaneously, like a list of different objects.
Tap to reveal reality
Reality:A union type field returns exactly one object of one of the possible types, never multiple types at once.
Why it matters:Believing unions return multiple types can lead to incorrect query design and runtime errors.
Quick: Do union types require all member types to share the same fields? Commit to yes or no.
Common Belief:All types in a union must have the same fields to be compatible.
Tap to reveal reality
Reality:Union types do not require shared fields; member types can be completely different.
Why it matters:Confusing unions with interfaces can cause schema design mistakes and limit API flexibility.
Quick: Can you query fields directly on a union type without specifying the concrete type? Commit to yes or no.
Common Belief:You can query any field on a union type directly without specifying which type it is.
Tap to reveal reality
Reality:You must use inline fragments to query fields on specific types within a union; direct querying is not allowed.
Why it matters:Not using inline fragments leads to query errors and confusion about how to access data.
Quick: Does using many union types always improve API clarity? Commit to yes or no.
Common Belief:More union types always make the API more flexible and clearer.
Tap to reveal reality
Reality:Overusing union types can make queries complex and harder to maintain, reducing clarity.
Why it matters:Misusing unions can hurt developer experience and increase bugs in large APIs.
Expert Zone
1
Union types do not enforce any common fields, so clients must always handle each type case explicitly, which can increase query verbosity.
2
The __typename field is automatically added by GraphQL to help clients distinguish types, but some server implementations require explicit resolver support for unions.
3
Union types cannot be nested inside other unions or interfaces directly, which sometimes requires creative schema design to model complex data.
When NOT to use
Avoid union types when your types share common fields and behavior; use interfaces instead for better type safety and simpler queries. Also, if your API clients struggle with complex inline fragments, consider simplifying the schema or using custom scalar types.
Production Patterns
In production, union types are often used for search results, error handling (e.g., success or error types), and polymorphic fields where the exact type varies. Developers combine unions with interfaces and careful resolver logic to build flexible yet maintainable APIs.
Connections
Polymorphism in Object-Oriented Programming
Union types provide a form of polymorphism by allowing a variable to hold objects of different types.
Understanding polymorphism helps grasp how union types let a field represent multiple possible types, similar to how objects can be treated as instances of different classes.
Tagged Unions in Functional Programming
Union types in GraphQL are similar to tagged unions or sum types, which hold a value that can be one of several types, tagged with its actual type.
Knowing tagged unions clarifies why GraphQL uses __typename to tag the actual type, enabling safe access to the correct data shape.
Type Systems in Programming Languages
Union types relate to type systems that allow variables to hold values of multiple types, enhancing flexibility while preserving type safety.
Recognizing this connection helps understand the balance GraphQL strikes between flexible data shapes and predictable query results.
Common Pitfalls
#1Querying union type fields without inline fragments.
Wrong approach:query { search(text: "1984") { title author } }
Correct approach:query { search(text: "1984") { ... on Book { title author } ... on Movie { title director } } }
Root cause:Misunderstanding that union types require specifying the concrete type to access fields.
#2Defining a union type with non-object types or scalar types.
Wrong approach:union Result = String | Book
Correct approach:union Result = Book | Movie
Root cause:Believing union types can include scalars or non-object types, which GraphQL does not allow.
#3Expecting a union field to return multiple objects at once.
Wrong approach:type Query { search(text: String): [SearchResult] } // But resolver returns multiple types in one object
Correct approach:type Query { search(text: String): SearchResult } // Resolver returns one object of one type per query
Root cause:Confusing union types with lists or arrays of multiple types.
Key Takeaways
Union types let a GraphQL field return one of several object types, increasing API flexibility.
You must use inline fragments in queries to access fields specific to each union member type.
Union types differ from interfaces because they do not require shared fields among member types.
The __typename field is crucial internally to identify which type a union field resolved to.
Overusing union types can complicate queries and reduce clarity, so use them thoughtfully.