Extending types For Data Modelling in GraphQL

Extending types For Data Modelling in GraphQL

·

4 min read

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.