Interfaces and Unions
So far every field has had exactly one object type. But real domains have polymorphism: a search result might be a user or a post; a notification might be a mention, a like, or a follow. GraphQL has two abstract types for this — interfaces and unions — and a way to select the right fields per concrete type using inline fragments. This lesson covers all three and, crucially, when to use which.
Interfaces — shared fields across related types
Section titled “Interfaces — shared fields across related types”An interface declares a set of fields that several object types all promise to provide. Any type that implements the interface must include those fields. Use an interface when several types are genuinely variations of one concept and share data:
interface Media { id: ID! title: String! durationSeconds: Int!}
type Episode implements Media { id: ID! title: String! durationSeconds: Int! seasonNumber: Int!}
type Movie implements Media { id: ID! title: String! durationSeconds: Int! rating: String}Both Episode and Movie are Media: they share id, title, and durationSeconds, but each adds its own fields. A field can now return the interface — media: [Media!]! — and the value will be one of the implementing types at runtime.
Unions — one of several unrelated types
Section titled “Unions — one of several unrelated types”A union says a value is exactly one of a listed set of object types, with no required shared fields. Use a union when the alternatives do not naturally share data — they just happen to appear in the same slot:
union SearchResult = Episode | Movie | Person
type Person { id: ID! name: String!}
type Query { search(term: String!): [SearchResult!]!}A SearchResult is an Episode, a Movie, or a Person. There is no field every search result must have — a Person has nothing in common with a Movie beyond turning up in the same list. That is the signal for a union rather than an interface.
flowchart TD Interface["interface Media (shared: id, title, durationSeconds)"] Episode["type Episode"] Movie["type Movie"] Interface --> Episode Interface --> Movie Union["union SearchResult (no shared fields)"] Person["type Person"] Union --> Episode Union --> Movie Union --> Person
__typename and inline fragments
Section titled “__typename and inline fragments”When a field can return more than one concrete type, the client needs a way to ask “which one is this, and give me its specific fields.” GraphQL provides the built-in __typename field — it returns the concrete type’s name as a string — and inline fragments to select fields conditionally per type:
{ search(term: "graph") { __typename ... on Episode { title seasonNumber } ... on Movie { title rating } ... on Person { name } }}Read ... on Movie as “if this result is a Movie, also select these fields.” For an interface you can select the shared fields directly (no fragment needed) and use inline fragments only for the type-specific extras. __typename is almost always worth requesting on a polymorphic field — clients use it to decide which branch of their own code to run.
A union with fragments, run for real
Section titled “A union with fragments, run for real”The example below defines a Media union of Episode and Movie, returns a mixed list, and uses __typename plus inline fragments to pull the right fields from each. Press Run.
Each item in the list came back tagged with its __typename, and only the inline fragment matching that type contributed fields. The Episode carried seasonNumber; the Movie carried rating. One field, two shapes, fully type-safe.