Extending types For Data Modelling in GraphQL
GraphQL is very good at helping you compose your data from different data sources, for example, by using federation. Type extensions can be very helpful when you're using GraphQL as a data layer or gateway for all your data. GraphQL type extensions allow you to add or replace fields on types that already exist in your schema. This way, you can better organize your data from different sources.
Let's explore how type extensions help with data modeling in GraphQL.
What are Type Extensions
Type extensions help you with data modeling in GraphQL, primarily when you work with different data sources. Or want to modify third-party data types that you cannot change directly.
In the GraphQL specification, you can find multiple definitions of type extensions, where "object extensions" are the most common ones. The section 3.6.3. Object Extensions describes how you can use the extend
keyword to add or replace fields to an object type.
An example of extending a type would be to the following:
type Person {
id: String
name: String
age: Int
}
extend type Person {
email: String
}
The type Person
will now have the fields id
, name
, age
, and email
. When we go back to the earlier statement about data composition when working with multiple data sources, this example would be perfect for a situation where the fields id
, name
, and age
come from one source of data (for example, a database). And email
comes from another data source, let's say a CRM.
In StepZen, this means that the GraphQL schema would look something like this:
type Person {
id: String
name: String
age: Int
}
extend type Person {
email: String
@materializer (query: "getPersonEmail", arguments: [{name: "personId", field: "id"}]
}
type Query {
getPerson(id: ID!): Person
@dbquery(
type: "mysql"
table: "person"
configuration: "mysql_config"
)
getPersonEmail(personId: ID!): String
@rest (endpoint: "https://some.crm.com/api/person/$personId/email")
}
The GraphQL schema above will get the fields for the type Person
from the MySQL database using a @dbquery
connector. For the extended field email
it will use @materializer
to get the data from a CRM system using its REST API.
If the database contained an email
field, it could also be overwritten when using type extensions, as StepZen will always prefer the extended object types.
GraphQL also supports inheritance, which is often seen as an alternative to type extensions. Inheritance is focused on reusing rather than extending types, as you'll learn in the next section.
Extending types versus inheritance
There's a difference between type extensions and inheritance. You can use inheritance to compose your data in many programming languages or type systems, and GraphQL is no different.
With inheritance in GraphQL, you can reuse field definitions by using interfaces, meaning you can assign a set of fields to every type that implements this interface. The implementations of this interface only share the types of the interface.
Suppose you have a company that has both full-time employees and seasonal employees that only work in the winter or summer season.
interface Employee {
id: ID
name: String
email: String
}
type FullTimeEmployee implements Employee {
id: ID
name: String
email: String
monthlyWage: Float
}
type SeasonalEmployee implements Employee {
id: ID
name: String
email: String
hourlyWage: Float
season: String
}
The interface Employee
has the fields id
, name
, and email
, which is the data the company stores for every employee for example in a database or CRM. Employees working full-time are paid a monthly wage, while a seasonal employee receives an hourly wage instead. Also, the company stores the season the employee is active in.
As both FullTimeEmployee
and SeasonalEmployee
are implementing the interface Employee
, you have the certainty that the definitions of the fields id
, name
, and email
are the same across all employees.
Conclusion
GraphQL can be used as a data layer or gateway to compose this data when working with multiple data sources. Modeling your data in this setup can be done by using type extensions or, in some cases, by using inheritance. This post described how you could use object extensions to extend a type with fields coming from a different data source and inheritance to reuse field definitions for different ones.
Want to try this out? Head over to the Getting Started section and start building your GraphQL API. Follow us on Twitter or join our Discord community to ask for help when you run into any issue.