A Beginner’s Guide to GraphQL Interfaces and Unions
Learn about Interfaces and Unions in GraphQL, key concepts that simplify API development by allowing flexible data querying and improving query efficiency.
Join the DZone community and get the full member experience.
Join For FreeWhat is GraphQL?
GraphQL is an open-source query language for APIs, initially developed by Facebook in 2012 and released to the public in 2015. It offers a flexible and efficient alternative to traditional REST APIs by allowing clients to request only the specific data they need, solving issues of over-fetching and under-fetching that often occur with REST APIs.
One of the reasons for GraphQL’s growing popularity is its client-driven nature. This makes it particularly well-suited for modern applications where performance, scalability, and seamless user experiences are critical. GraphQL enables clients to combine multiple resources into a single request, reducing network traffic and making it an excellent solution for mobile apps with limited bandwidth or complex front-end needs.
Major companies like GitHub, Twitter, Indeed, and Shopify have embraced GraphQL, highlighting its potential to streamline API development and improve client-server interactions.
GraphQL Interface
In GraphQL, an Interface functions similarly to interfaces in object-oriented programming. It is an abstract type that defines a set of common fields that multiple object types can implement. This ensures that the client can confidently query these common fields across different types.
type Query {
findVehicles(): [Vehicle!]!
}
interface Vehicle {
id: ID!
name: String!
model: String
}
type Car implements Vehicle {
id: ID!
name: String!
model: String
# Specific to Car
fuelType: String!
}
type Bicycle implements Vehicle {
id: ID!
name: String!
model: String
# Specific to Bicycle
gearCount: Int!
isElectric: Boolean!
}
GraphQL client query:
query findVehicles() {
findVehicles() {
vehicle {
id,
name,
model,
... on Car {
fuelType
}
... on Bicycle {
gearCount,
isElectric
}
}
}
}
In this example, the common fields like id
, name
, and model
are available across all object types that implement the Vehicle
interface. However, the type-specific fields like fuelType
for Car
and gearCount
and isElectric
for Bicycle
can be queried using fragments.
If the client only needs common fields, they can omit the fragments:
query findCars() {
findCars() {
car {
id,
name,
model
}
}
}
Benefits of Using Interfaces
- Code Reusability: Common fields can be defined in the interface and shared across multiple types, reducing redundancy.
- Simplified Client-Side Logic: Clients don’t need conditional checks for object types. They can request exact types and confidently handle responses.
- Schema Extensibility: Adding a new common field becomes easier since it only needs to be defined in the interface.
- Enforced Structure: Interfaces enforce a shared structure across all implementing types, ensuring consistency (e.g., all vehicles must have an
id
,name
, andmodel
). - Unified Querying: Instead of querying different types individually, clients can query a single interface to retrieve data from all implementing types.
- Improved Documentation: By defining common behavior through interfaces, it becomes easier for API consumers to understand and work with related types.
GraphQL Union
A Union in GraphQL is an abstract type that allows clients to query multiple object types that are related in some aspect through a single field. Unlike interfaces, unions do not require the member types to share common fields. This makes unions ideal for handling cases where related types have different structures but need to be queried together.
type Query {
getPurchaseItems(): [PurchaseItem!]!
}
union PurchaseItem = Product | Service | Subscription
type Product {
id: ID!
productName: String!
price: Float!
}
type Service {
id: ID!
serviceName: String
duration: Float
}
type Subscription {
id: ID!
planName: String
billingCycle: String
}
GraphQL client query:
query getPurchaseItems() {
getPurchaseItems() {
purchaseItems {
... on Product {
id
productName
price
}
... on Service {
id
serviceName
duration
}
... on Subscription {
id
planName
billingCycle
}
}
}
}
In this example, Product, Service, and Subscription are all distinct types that belong to the PurchaseItem union. The client can query all three types using fragments in a single query, even though they don’t share any fields.
Important note about unions, the member types of a Union type must all be Object base types; Scalar, Interface, and Union types must not be member types of a Union. Similarly, wrapping types must not be member types of a Union.
Benefits of Using Unions
- Flexible Grouping: Unions allow for querying related types that don’t share any common fields, which would be cumbersome to handle otherwise.
- Simplified Error Handling: Clients can use fragments to query specific types, reducing the need for complex conditional logic on the client side.
- Heterogeneous Data Handling: A single query can retrieve data from multiple types, simplifying the handling of varied data structures.
- Useful for Error Responses: Unions are particularly useful when you want to combine success responses and error details into a single response type, allowing clients to handle them efficiently.
In Summary
GraphQL Interfaces and Unions offer powerful ways to structure your GraphQL schema, enabling flexibility and simplifying client-server interactions. Interfaces allow shared fields across types, promoting code reusability and easier schema extensions. Unions, on the other hand, offer a way to query disparate types together without requiring common fields.
Opinions expressed by DZone contributors are their own.
Comments