Interfaces and Unions
Interfaces and unions are GraphQL's two abstract types — they let a field return one of several possible concrete object types instead of a single fixed type. An interface (interface Node { id: ID! }) declares a set of fields that every implementing object type must include, so any type that implements it is guaranteed to expose those fields; a union (union SearchResult = Post | User | Comment) makes no such guarantee and simply lists the possible concrete types with nothing shared between them.
Cricket analogy: An 'AllRounder' role in cricket guarantees a player contributes both batting and bowling stats no matter which team they're on — like an interface guaranteeing shared fields — whereas a 'Man of the Match' award could go to a batsman, bowler, or fielder with no shared stat requirement, like a union.
Querying Abstract Types with Fragments
Because the client can't know in advance which concrete type an interface or union field will resolve to, GraphQL requires inline fragments (... on TypeName) or named fragments to select type-specific fields; you can select the shared interface fields directly, but anything specific to one implementing type must be guarded behind a fragment. At runtime, the server needs a resolveType function (or a __typename per object) to decide which concrete GraphQL type a given resolved value maps to, which is why every object implementing an interface or belonging to a union must be independently registered in the schema.
Cricket analogy: A commentator can describe any 'AllRounder' by their combined stats directly, but to discuss a specific player's unique bowling action (say Kuldeep Yadav's wrist-spin grip) they have to switch into player-specific commentary — just as GraphQL needs an inline fragment for type-specific fields.
interface Node {
id: ID!
}
interface Character {
id: ID!
name: String!
}
type Hero implements Character & Node {
id: ID!
name: String!
powerLevel: Int!
}
type Villain implements Character & Node {
id: ID!
name: String!
threatLevel: Int!
}
union SearchResult = Hero | Villain | Post
query {
search(term: "storm") {
__typename
... on Hero {
powerLevel
}
... on Villain {
threatLevel
}
... on Post {
title
}
}
}Always request __typename when querying a union or interface field, even outside of fragments — client libraries like Apollo Client use it to normalize the cache correctly, and it's the cheapest way for the client to know which concrete type came back.
Forgetting to register a resolveType (or __typename-based type-resolution) for every object implementing an interface will cause the server to throw a runtime 'Abstract type X must resolve to an Object type' error — this only surfaces when that field is actually queried, so it's easy to miss in testing until a specific type is hit.
- Interfaces guarantee a shared set of fields across every implementing object type.
- Unions list a set of possible concrete types with no shared field contract at all.
- Client queries must use inline (
... on Type) or named fragments to select type-specific fields. __typenametells the client which concrete type a polymorphic field actually resolved to.- The server needs a resolveType strategy so execution knows which concrete type a resolved value maps to.
- An object type can implement multiple interfaces simultaneously using
implements A & B. - Omitting resolveType logic for a type only fails at runtime when that type is actually returned.
Practice what you learned
1. What is the key difference between a GraphQL interface and a union?
2. How do you select fields specific to one concrete type within a query on an interface field?
3. Why is `__typename` commonly requested in queries against unions or interfaces?
4. What happens if the server lacks resolveType logic for a type implementing an interface?
5. Can a single object type implement more than one interface?
Was this page helpful?
You May Also Like
The Type System In Depth
A deep dive into how GraphQL's schema — scalars, object types, input types, and list/non-null modifiers — forms the typed contract between client and server.
Enums in GraphQL
How GraphQL enums restrict fields and arguments to a fixed, validated set of named values, and how their SDL names map to internal server representations.
Custom Scalars
How to model domain-specific leaf values beyond GraphQL's five built-in scalars using serialize, parseValue, and parseLiteral.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics