Bird
Raised Fist0
GraphQLquery~15 mins

Interface types in GraphQL - Deep Dive

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Overview - Interface types
What is it?
Interface types in GraphQL define a set of fields that multiple object types can share. They act like a contract, ensuring that any object implementing the interface has those fields. This helps clients query different types in a consistent way without knowing the exact type beforehand. Interfaces allow flexible and reusable schemas.
Why it matters
Without interface types, clients would need to know the exact object types to query, making APIs rigid and harder to evolve. Interfaces solve this by letting clients ask for common fields across different types, improving flexibility and reducing repeated code. This makes APIs easier to maintain and extend as new types are added.
Where it fits
Before learning interfaces, you should understand basic GraphQL object types and schemas. After mastering interfaces, you can explore unions, fragments, and advanced schema design patterns that build on interfaces for more powerful queries.
Mental Model
Core Idea
An interface type is a shared blueprint that multiple object types follow, allowing clients to query common fields without knowing the exact object type.
Think of it like...
Think of an interface like a job description that several employees share. Each employee (object type) has their own details but all must have the skills listed in the job description (interface). This way, you can ask any employee about those skills without needing to know who exactly they are.
┌───────────────┐
│  Interface    │
│  (e.g. Animal)│
│  - name       │
│  - age        │
└──────┬────────┘
       │ implements
  ┌────┴─────┐    ┌─────────────┐
  │  Dog     │    │   Cat       │
  │ - name   │    │ - name      │
  │ - age    │    │ - age       │
  │ - breed  │    │ - color     │
  └─────────┘    └─────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding GraphQL Object Types
🤔
Concept: Learn what object types are and how they define data shapes in GraphQL.
In GraphQL, an object type defines a set of fields that describe a kind of data. For example, a 'User' type might have fields like 'id', 'name', and 'email'. Clients query these fields to get data. Object types are the building blocks of a GraphQL schema.
Result
You can write queries that ask for specific fields on object types and get structured data back.
Understanding object types is essential because interfaces build on this concept by grouping common fields across multiple object types.
2
FoundationWhat is a GraphQL Interface Type?
🤔
Concept: Introduce the interface type as a way to define common fields shared by multiple object types.
An interface type declares fields that multiple object types must implement. For example, an 'Animal' interface might require 'name' and 'age' fields. Any object type like 'Dog' or 'Cat' that implements 'Animal' must have those fields. This allows clients to query 'Animal' and get data from any implementing type.
Result
You can query an interface and receive data from any object type that implements it, ensuring consistent fields.
Interfaces let you write flexible queries that work across different types sharing common fields, reducing duplication.
3
IntermediateImplementing Interfaces in Object Types
🤔Before reading on: Do you think an object type can implement multiple interfaces or just one? Commit to your answer.
Concept: Learn how object types declare they implement interfaces and what that means for their fields.
In GraphQL schema, an object type declares it implements an interface using the 'implements' keyword. It must then include all fields from the interface. For example: interface Animal { name: String! age: Int } type Dog implements Animal { name: String! age: Int breed: String } Here, 'Dog' must have 'name' and 'age' fields because it implements 'Animal'.
Result
The schema enforces that 'Dog' has all fields from 'Animal', plus any extra fields it defines.
Knowing that object types must fully implement interface fields ensures data consistency and predictable queries.
4
IntermediateQuerying Interface Types with Fragments
🤔Before reading on: When querying an interface, do you think you can only ask for interface fields or also fields specific to implementing types? Commit to your answer.
Concept: Learn how to write queries that get common interface fields and also fields unique to specific object types using fragments.
When querying an interface, you can ask for the fields defined by the interface directly. To get fields specific to a particular object type, you use inline fragments with the '... on TypeName' syntax. For example: query { animals { name age ... on Dog { breed } ... on Cat { color } } } This query fetches common fields 'name' and 'age' from all animals, and 'breed' only for dogs, 'color' only for cats.
Result
The query returns a list of animals with their common fields and type-specific fields where applicable.
Fragments let you combine flexible interface queries with type-specific details, making your queries powerful and precise.
5
IntermediateInterface Type Resolution at Runtime
🤔Before reading on: Do you think the server automatically knows which object type implements an interface for each result, or do you have to specify it? Commit to your answer.
Concept: Understand how GraphQL determines the actual object type behind an interface when returning data.
At runtime, when a query asks for an interface, the server must resolve which concrete object type each result is. This is done by the server's resolver functions returning the correct type name or by using a special '__resolveType' function. This lets GraphQL know how to handle fragments and fields specific to that type.
Result
The client receives data with the correct type information, enabling proper field resolution.
Knowing how type resolution works helps you design resolvers that correctly identify object types, avoiding query errors.
6
AdvancedInterfaces vs Unions: Choosing the Right Tool
🤔Before reading on: Do you think interfaces and unions are the same or serve different purposes? Commit to your answer.
Concept: Learn the difference between interfaces and unions and when to use each in GraphQL schemas.
Interfaces define a set of common fields that implementing types must have. Unions group types without requiring shared fields. Use interfaces when you want to query common fields across types. Use unions when types are related but have no common fields. For example, 'Animal' interface vs 'SearchResult' union of 'User' or 'Post'.
Result
You can design schemas that are both flexible and precise by choosing interfaces or unions appropriately.
Understanding this distinction prevents schema design mistakes that limit query flexibility or cause confusion.
7
ExpertPerformance and Schema Evolution with Interfaces
🤔Before reading on: Do you think adding fields to an interface always breaks clients or can it be done safely? Commit to your answer.
Concept: Explore how interfaces impact query performance and how to evolve schemas without breaking clients.
Interfaces can improve query performance by allowing clients to request only needed fields across types. However, adding non-nullable fields to an interface can break existing clients. To evolve safely, add nullable fields or create new interfaces. Also, complex interface hierarchies can increase server resolver complexity, so balance design carefully.
Result
You can maintain backward compatibility and optimize performance by thoughtful interface design and evolution.
Knowing interface evolution rules helps avoid breaking APIs and supports smooth client upgrades in production.
Under the Hood
Internally, GraphQL servers use interface definitions to enforce that implementing object types include required fields. When a query requests an interface, the server uses resolver functions to fetch data and a type resolver to identify the concrete object type for each result. This type information guides the server in resolving fields and fragments specific to that type before sending the response.
Why designed this way?
Interfaces were designed to provide a flexible yet consistent way to query related but different object types. They solve the problem of querying heterogeneous data with shared fields without forcing clients to know exact types. This design balances type safety, query flexibility, and schema evolution, unlike unions which lack field guarantees.
┌───────────────┐
│  Query        │
│  { animals }  │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Resolver      │
│ fetches data  │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Type Resolver │
│ determines    │
│ concrete type │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Field Resolver│
│ resolves      │
│ fields based  │
│ on type       │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Response sent │
│ to client     │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Can an interface type be queried directly without any implementing object types? Commit to yes or no.
Common Belief:An interface type can be queried on its own like an object type, even if no object types implement it.
Tap to reveal reality
Reality:Interfaces cannot be queried directly unless there are object types that implement them. They only define a contract, not concrete data.
Why it matters:Trying to query an interface without implementations results in errors or empty data, confusing clients and breaking queries.
Quick: Do you think all fields in an interface must be non-nullable? Commit to yes or no.
Common Belief:All interface fields must be non-nullable to ensure data consistency.
Tap to reveal reality
Reality:Interface fields can be nullable or non-nullable. Making fields non-nullable requires all implementations to provide those fields, which can be restrictive.
Why it matters:Misunderstanding this can lead to overly strict schemas that are hard to evolve or too loose schemas that cause runtime errors.
Quick: Does implementing multiple interfaces mean an object type inherits all fields automatically? Commit to yes or no.
Common Belief:Implementing multiple interfaces means the object type automatically has all their fields without declaring them.
Tap to reveal reality
Reality:Object types must explicitly declare all fields from each interface they implement. The schema enforces this, but the object type definition must include them.
Why it matters:Assuming automatic inheritance can cause missing fields in the schema, leading to validation errors or incomplete data.
Quick: Can interfaces be used to enforce field arguments or only field presence? Commit to yes or no.
Common Belief:Interfaces can enforce the arguments that fields accept, not just the fields themselves.
Tap to reveal reality
Reality:Interfaces only enforce the presence and type of fields, not the arguments those fields accept. Arguments can differ in implementations.
Why it matters:Expecting argument enforcement can cause confusion when clients rely on arguments that are not consistent across implementations.
Expert Zone
1
Interfaces can be extended by other interfaces, allowing layered contracts that increase schema flexibility and reuse.
2
Resolvers for interfaces often require custom '__resolveType' functions to correctly identify object types, especially in complex schemas or federated setups.
3
Using interfaces with schema stitching or federation requires careful coordination to maintain consistent type resolution across services.
When NOT to use
Avoid interfaces when the grouped types do not share any common fields; use unions instead. Also, if you need to enforce strict argument consistency on fields, interfaces are insufficient. For very dynamic or loosely related types, consider unions or custom scalar types.
Production Patterns
In production, interfaces are used to model polymorphic data like search results, notifications, or content types. They enable clients to write generic queries that adapt as new types are added. Interfaces combined with fragments allow efficient data fetching and reduce over-fetching. They also support schema evolution by adding new implementing types without breaking clients.
Connections
Object-Oriented Programming Interfaces
Same pattern of defining a contract that multiple types/classes must follow.
Understanding OOP interfaces helps grasp GraphQL interfaces as they both enforce shared structure and behavior across different implementations.
Polymorphism in Programming
Interfaces enable polymorphic queries where the same query works on different types with shared fields.
Knowing polymorphism clarifies how GraphQL interfaces allow flexible data access without knowing exact types upfront.
Database Views
Interfaces act like virtual views that unify different tables (types) under common columns (fields).
Seeing interfaces as views helps understand how they provide a consistent interface to diverse underlying data.
Common Pitfalls
#1Querying interface fields without implementing types defined in schema.
Wrong approach:query { unknownInterface { commonField } }
Correct approach:query { knownInterface { commonField } }
Root cause:Trying to query an interface that has no object types implementing it causes errors or empty results.
#2Defining an object type that claims to implement an interface but missing required fields.
Wrong approach:type Bird implements Animal { name: String! // missing 'age' field from Animal wingSpan: Int }
Correct approach:type Bird implements Animal { name: String! age: Int wingSpan: Int }
Root cause:Misunderstanding that all interface fields must be explicitly declared in implementing types.
#3Assuming interface fields enforce argument consistency across implementations.
Wrong approach:interface SearchResult { summary(limit: Int): String } type Article implements SearchResult { summary(limit: Int): String } type User implements SearchResult { summary(): String // missing argument 'limit' }
Correct approach:interface SearchResult { summary(limit: Int): String } type Article implements SearchResult { summary(limit: Int): String } type User implements SearchResult { summary(limit: Int): String }
Root cause:Believing interfaces enforce argument signatures, which they do not.
Key Takeaways
Interface types define shared fields that multiple object types must implement, enabling flexible and consistent queries.
Clients can query interfaces to get common fields and use fragments to access type-specific fields safely.
At runtime, the server resolves the actual object type behind an interface to correctly fulfill queries.
Interfaces differ from unions by requiring shared fields, making them suitable for polymorphic data with common structure.
Careful interface design supports schema evolution and prevents breaking clients while maintaining query flexibility.

Practice

(1/5)
1. What is the main purpose of an interface in GraphQL?
easy
A. To define a set of fields that multiple types must implement
B. To create a new scalar type
C. To specify a query operation
D. To define a mutation resolver

Solution

  1. Step 1: Understand the role of interfaces

    Interfaces in GraphQL define common fields that multiple types share.
  2. Step 2: Compare options with interface purpose

    Only To define a set of fields that multiple types must implement correctly states that interfaces define shared fields for multiple types.
  3. Final Answer:

    To define a set of fields that multiple types must implement -> Option A
  4. Quick Check:

    Interface = shared fields [OK]
Hint: Interfaces define shared fields for multiple types [OK]
Common Mistakes:
  • Confusing interfaces with scalar types
  • Thinking interfaces define queries or mutations
  • Assuming interfaces can be instantiated directly
2. Which of the following is the correct syntax to declare an interface named Node with a field id of type ID!?
easy
A. interface Node { id: ID! }
B. interface Node { id: ID }
C. interface Node id: ID!
D. interface Node { id: String! }

Solution

  1. Step 1: Recall GraphQL interface syntax

    Interfaces are declared with the keyword interface, followed by the name and fields with types.
  2. Step 2: Check field type correctness

    The field id must be non-nullable ID!, so interface Node { id: ID! } matches exactly.
  3. Final Answer:

    interface Node { id: ID! } -> Option A
  4. Quick Check:

    Correct interface syntax = interface Node { id: ID! } [OK]
Hint: Use 'interface Name { field: Type! }' syntax exactly [OK]
Common Mistakes:
  • Omitting the exclamation mark for non-nullable
  • Using wrong scalar type like String instead of ID
  • Missing braces around fields
3. Given the interface and types below, what will the query { search { id name } return?
interface SearchResult {
  id: ID!
}
type User implements SearchResult {
  id: ID!
  name: String!
}
type Product implements SearchResult {
  id: ID!
  name: String!
  price: Float!
}
medium
A. A list of objects each with fields id and name
B. A list of objects with only id fields
C. An error because price is missing in the interface
D. A syntax error because name is not in the interface

Solution

  1. Step 1: Review the interface definition

    The SearchResult interface only defines id: ID!. The name field is present in implementing types but not in the interface.
  2. Step 2: Analyze the query against the interface

    Querying name directly on search (SearchResult) fails because it is not defined on the interface. GraphQL requires inline fragments for type-specific fields like ... on User { name }.
  3. Final Answer:

    A syntax error because name is not in the interface -> Option D
  4. Quick Check:

    Directly query only interface fields; use fragments for type-specific [OK]
Hint: Query only interface fields directly; use fragments for type-specific fields [OK]
Common Mistakes:
  • Assuming only interface fields can be queried
  • Expecting error if extra fields exist in types
  • Confusing interface fields with type-specific fields
4. Consider the following schema snippet:
interface Vehicle {
  id: ID!
  speed: Int!
}
type Car implements Vehicle {
  id: ID!
  speed: Int!
  brand: String!
}
type Bike implements Vehicle {
  id: ID!
  brand: String!
}
What is the error in this schema?
medium
A. Car type has an extra field brand not in Vehicle interface
B. Bike type is missing the required speed field from Vehicle interface
C. Vehicle interface cannot have fields of type Int
D. Interface Vehicle must be a type, not an interface

Solution

  1. Step 1: Check interface field requirements

    All types implementing an interface must have all interface fields with matching types.
  2. Step 2: Verify Bike type fields

    Bike implements Vehicle but lacks the speed field required by Vehicle, causing an error.
  3. Final Answer:

    Bike type is missing the required speed field from Vehicle interface -> Option B
  4. Quick Check:

    Implementing types must have all interface fields [OK]
Hint: Check all interface fields are implemented in each type [OK]
Common Mistakes:
  • Thinking extra fields in types cause errors
  • Ignoring missing interface fields in types
  • Confusing interface with type declaration rules
5. You want to design a GraphQL schema where multiple types like Book and Movie share fields id and title, but each has unique fields too. How should you use interfaces to achieve this?
hard
A. Use scalar types for id and title in each type separately
B. Create a union type of Book and Movie without shared fields
C. Define an interface Item with id and title, then have Book and Movie implement Item and add their unique fields
D. Define Book and Movie as separate types without interfaces

Solution

  1. Step 1: Identify shared fields and unique fields

    Both Book and Movie share id and title, but have unique fields.
  2. Step 2: Use interface for shared fields

    Defining an interface Item with shared fields and implementing it in Book and Movie allows reuse and flexibility.
  3. Step 3: Add unique fields in each type

    Book and Movie can add their own fields beyond the interface.
  4. Final Answer:

    Define an interface Item with id and title, then have Book and Movie implement Item and add their unique fields -> Option C
  5. Quick Check:

    Interfaces = shared fields + types add unique fields [OK]
Hint: Use interfaces for shared fields, types add unique fields [OK]
Common Mistakes:
  • Using union types instead of interfaces for shared fields
  • Duplicating shared fields in each type without interface
  • Misusing scalar types for shared fields