GraphQL Interfaces
An interface defines a set of fields that multiple types must include. Any type that implements an interface guarantees those fields exist. Interfaces let you write queries that work across different types that share common fields.
The Problem Interfaces Solve
A content platform has Articles, Videos, and Podcasts. All three share a title, author, and publish date. Without an interface, you write three separate queries for three different types. With an interface, you write one query that works for all content types through the shared fields.
Without interface: With interface:
────────────────── ───────────────
Article { title, author } interface Content {
Video { title, author } title: String!
Podcast { title, author } author: String!
publishedAt: String!
3 separate queries needed }
Article implements Content
Video implements Content
Podcast implements Content
1 query using Content fields
Defining an Interface
interface Vehicle {
id: ID!
manufacturer: String!
topSpeed: Int!
}
type Car implements Vehicle {
id: ID! ← Required by interface
manufacturer: String! ← Required by interface
topSpeed: Int! ← Required by interface
doors: Int! ← Extra field, Car-specific
}
type Motorcycle implements Vehicle {
id: ID! ← Required by interface
manufacturer: String! ← Required by interface
topSpeed: Int! ← Required by interface
sidecar: Boolean ← Extra field, Motorcycle-specific
}
Querying Through an Interface
A query can target the interface type. Common fields are available directly. Type-specific fields require an inline fragment with ... on TypeName.
Schema:
────────
type Query {
vehicles: [Vehicle] ← Returns a mix of Car and Motorcycle
}
Query:
───────
{
vehicles {
manufacturer ← Works for ALL Vehicle types
topSpeed ← Works for ALL Vehicle types
... on Car {
doors ← Only for Car objects
}
... on Motorcycle {
sidecar ← Only for Motorcycle objects
}
}
}
Response:
──────────
{
"vehicles": [
{
"manufacturer": "Honda",
"topSpeed": 220,
"doors": 4 ← Car fields included
},
{
"manufacturer": "Royal Enfield",
"topSpeed": 160,
"sidecar": false ← Motorcycle fields included
}
]
}
The __typename Meta Field
The __typename field tells you which concrete type an object is at runtime. This is useful when your client needs to know whether it received a Car or a Motorcycle to render the right component.
{
vehicles {
__typename ← Ask what type this is
manufacturer
... on Car {
doors
}
}
}
Response:
──────────
{
"vehicles": [
{ "__typename": "Car", "manufacturer": "Honda", "doors": 4 },
{ "__typename": "Motorcycle", "manufacturer": "Royal Enfield" }
]
}
One Type Can Implement Multiple Interfaces
interface Identifiable { id: ID! }
interface Timestamped { createdAt: String! }
type Post implements Identifiable & Timestamped {
id: ID!
createdAt: String!
title: String!
}
Key Points
- An interface defines required fields that implementing types must include.
- Multiple types can implement the same interface, sharing a common query surface.
- Query interface fields directly; use
... on TypeNameinline fragments for type-specific fields. - The
__typenamemeta field identifies the concrete type of an object at runtime. - A type can implement multiple interfaces by listing them with
&.
