patterntypescriptgraphqlModerate
Type unions and interfaces in GraphQL — model polymorphic data correctly
Viewed 0 times
unioninterfacepolymorphism__resolveTypeinline fragmentsdiscriminated union
Error Messages
Problem
A field can return one of several different object types (search results, notification types, media items). Representing this as a single generic type loses type safety and requires clients to check a
type field manually.Solution
Use unions for 'one of these unrelated types', interfaces for 'shared fields across related types'.
# Interface — shared shape
interface Node {
id: ID!
}
interface Media {
id: ID!
url: String!
mimeType: String!
}
type Image implements Media & Node {
id: ID!
url: String!
mimeType: String!
width: Int!
height: Int!
}
type Video implements Media & Node {
id: ID!
url: String!
mimeType: String!
duration: Float!
}
# Union — unrelated types
union SearchResult = User | Post | Product
type Query {
search(q: String!): [SearchResult!]!
}# Client query with inline fragments
query Search($q: String!) {
search(q: $q) {
... on User { id name }
... on Post { id title }
... on Product { id sku }
}
}Why
Unions and interfaces push type discrimination into the schema where the type system enforces it. Clients get type-safe exhaustive handling. Code generators produce discriminated union TypeScript types.
Gotchas
- Union members cannot share field access without inline fragments — there are no 'common union fields'
- Interfaces CAN have shared fields queried without inline fragments
- You must implement
__resolveTypeon union and interface types in your resolvers - Adding a new member to a union is technically a breaking change — clients that don't handle the new type via
... on NewTypewill silently drop data
Context
Modeling heterogeneous data like search results, notification feeds, or media libraries
Revisions (0)
No revisions yet.