More GraphQL Schemas and Types

Spread the love

GraphQL is a query language for our API and a server-side runtime for running queries by using a type system for our data.

In this article, we’ll look at some GraphQL data types including lists, required fields, interfaces, union types, and input types.

Lists and Non-Null

A non-null type can be created by using the ! type modifier.

With that added, it’ll make sure that we have to include the field when we’re making a query to the server.

The non-null modifier can be used for defining arguments for a field, which causes the GraphQL server to return a validation error if a null value is passed as that argument.

Lists work in a similar way. We can use square brackets to mark something as a list.

For example, we can use them together as follows:

type Person {
  name: String!
  addresses: [Address]!

In the code above, we marked the name field as required and have the String type. Also, we have an addresses field which is a list of Address objects, and it’s also marked as required.

If we have something like:

myField: [String!]

This means that the list itself can be null, but myField can’t have any null members.

On the other hand, if we have:

myField: [String]!

then the list itself can’t be null, but it can contain null values.

We can nest any number of non-null and list modifiers according to our needs.


An interface is an abstract type that includes a certain set of fields that a type must include to implement the interface.

For example, we can create an interface as follows:

interface Person {
  id: ID!
  name: String!
  friends: [Person]

This means that a type that implements Person must have the exact fields as we listed above.

For example, we can create a type that implements the interface as follows:

type Employee implements Person{
  id: ID!
  name: String!
  friends: [Person],
  employeeId: String!

In the code above, we have the Employee type that has all the fields above. We also have the employeeId string.

Therefore, we can use interfaces to ensure that a type has at least the fields and types that are listed in the interface.

To query something with various types that are implemented by an interface, we can use inline fragments as follows:

query Employee($id: ID!) {
  employee(id: $id) {
    ... on Employee {

Union types

Unio types are similar to interfaces, but they don’t get to specify any common fields between types.

We can define a union type with the union keyword as follows:

union Worker = Person | Employee

We’ll need to use a conditional fragment to be able to query any fields:

  search(text: "an") {
    ... on Person {
    ... on Employee{

The __typename field is a String that indicates the type of the response object.

Input types

We can create input types to pass in whole objects into a request. For example, we can define an input type as follows:

input PersonInput {
  firstName: String!
  lastName: String!

Then we can pass it into a mutation as follows:

mutation CreatePerson($person: PersonInput!) {
  createReview(person: $person) {

The fields on an input object can refer to input object types, but we can’t mix input and output types in our schema. Input object types also can’t have arguments in their fields.


To make sure a field isn’t null we can use the exclamation mark to mark it non-null.

We can also use square brackets to mark that something is a list.

To define a list of set fields for types, we can use interfaces to make sure all types that implement an interface have the fields listed.

Union types are useful for letting us combine common fields of types that implement the same interface and avoid repeating fields in queries.

We can use input types to pass in whole objects into a mutation.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *