GraphQL Types system
Tags: graphql, opensource, programming, typesystem
Published: 2021-05-14 08:25:16

---
title: GraphQL Types system
published: true
description: "Type systems are built-in features of most programming languages, Their implementations differ from  language to languages and generally used to formalize and enforce a consistent criteria of how data should be stored, accessed"
tags: GraphQL, openSource, programming, typesystem
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5p3ef0zardd8hvipkqp.png
canonical_url: https://jaygurav.netlify.app/graphql/graphqlTypesSystem/
---
> Above image is from graphql.org

👉 This blogpost was originally publish at my personal [blog site](https://jaygurav.netlify.app/graphql/graphqlTypesSystem/)

---
Type systems are built in feature of most programming languages, Their implementations differ from language to languages and have occurrence to type check at compile-time or at run-time, may be manually annotated or system inferred. Type systems are part of long time academic study called Type theory. The fundamental problem that type theory addresses is that to ensure that programs have meaning, assigning a data type also termed as typing's gives meaning to a sequence of bits, gives it rules to live by.

According to [Wikipedia](https://en.wikipedia.org/wiki/Type_system)

>In programming languages, a type system is a logical system comprising a set of rules that assigns a property called a type to the various constructs of a computer program. The main purpose of a type system is to reduce possibilities for bugs in computer programs by defining interfaces between different parts of a computer program, and then checking that the parts have been connected in a consistent way.

## Type systems in GraphQL
As described in my article on [Why GraphQL?](https://dev.to/jaymgurav/why-graphql-k78), GraphQL query closely matches with the result that the query returns, So it much important and useful to have exact description of data we can ask, select and what kind of data it returns. Every GraphQL service, each level of query and fields corresponds to a particular type and each type describes a set of available fields.

Since GraphQL service can be written in any language and can’t specifically rely on language implementations to talk about GraphQL’s schema and types so, GraphQL comes with its own simple schema language called as “GraphQL schema language” similar to its query language allows GraphQL to talk about schemas and types in a language-agnostic way.

This type system is already a great advantage to API’s compared to REST API, Let’s take a ride into GraphQL type system in depth. There are different **kinds** of types in GraphQL and these kinds are classified as
- Scalar
- Object
- Input Object
- Union
- Interfaces
- List
- Non-Null

All these above types are defined as enumeration(enum) `__TypeKind` in GraphQL SDL(Schema Definition Language). One can speculate about Type Kinds in [GraphQL specs](https://spec.graphql.org/draft/#sec-Type-Kinds).

## Schema type and Root types
When creating a GraphQL server we need to first initialize it with our GraphQL schema, This Schema type serves as a first entry point to our whole schema. The Root type defines all the operations that are made available in the GraphQL server. The operations are **Query**, **Mutation** and **Subscription**. Most of the types in our schema are normal objects while a GraphQL service has to have a `query` type and may of may not have `mutation` and `subscription` types. These types are also same as a regular types but special in a way that they define entry point to every GraphQL
`query`, `mutation` and `subscription` types.

## Scalars and Enumeration types
Scalars and enums are primitive values in GraphQL. What it means is that the GraphQL objects, fields and everything in GraphQL has to resolve to something that is concrete and that’s what are scalars. As the specs says *they represent the leaves of the query*.

### Scalars

Consider an example below
```graphql
{
  user {
    name
    book: {
      title
      pages
    }
  }
}
# Would result in following JSON data
{ 
  “data”: {
    “user”: {
      “name”: “Jay”,
      “book”: {
        “title”: “Some book title”,
        “pages”: 200
      }
    }
  }
}
```
In the above query `name`, `title` and `pages` are fields that resolve to scalar types as they do not have any sub-fields and so represent the leaves of the query. book is a object type that resolves into fields that ultimately resolve into scalars.

In GraphQL there are two types of scalars
1. Built-in default scalars
2. Custom scalars or user-defined scalars

There are 5 built-in/default scalars
- Int: Signed 32 bit integer
- Float: Signed double-precision floating point
- String: A UTF-8 character sequence
- Boolean: `true` or `false`
- ID: A scalar type that represents unique identifier, is represented the same way as string but is intended to be not human readable, often used as a key for cache or objects

All data cannot be represented by these default types so For better representation of such data GraphQL allows to specify 
custom scalar types for example scalar `DateTime`

Now, the implementation of our custom scalar and how this is serialized, de-serialized, and validated is up to us.

> **kind** of this type must return `__TypeKind.SCALAR`

### Enumeration types
Enumeration types also called as *enums* , these are special kind of scalar that is restricted to a particular set of allowed values. Enums can also be used as input and output type objects. This allows us to
- Validate that any field of this type are one of those allowed values specified by that enum.
- States through type system that a field will always be one of a finite set of values

Lets see how enums are implemented using GraphQL SDL
```graphql
enum Gender {
  MASCULINE
  FEMININE
  COMMON
  NEUTER
}
input createUserInput { # later on this input object types
  name: String!
  email: String!
  gender: Gender!
}
query {
  createUser(input: createUserInput!): User!
}
```
This means wherever we use the type `Gender` in our schema, we expect it to be exactly one of the for values(i.e. MASCULINE, FEMININE, COMMON, NEUTER), so our `gender` field in `createUserInput` input argument should always be one of those allowed values.

## Object types and Input object
Objects are most commonly used types of GraphQL schema. we can see in our above example that book field might be represented as object type as follows

```graphql
type Book {
  title: String!
  pages: Int!
}
```

`Book` is a _GraphQL object type_ meaning its a type with some fields. `title` and `pages` are fields on `Book` type which eventually resolve into scalar type of `String` and `Int`. The exclamation mark on the end of the scalar type is a _modifier_ which represents a **non-nullable** field, means a GraphQL service promises return you a value of promised type when you query that field.

GraphQL Object type are categorized into two types

- Input types
- Output types

Lets look at what GraphQL specification has to say about why Objects are categorized into these separate types

> Objects can contain fields that express circular references or references to interfaces and unions, neither of which is appropriate for use as an input argument. For this reason, input objects have their own separate type in the system.

input types are defined as follows

```graphql
input createBookInput {
  title: String!
  pages: Int!
}

mutation createBook(input: createBookInput!): Book!
```
> I find it a good practice to use **Action-type + ObjectThatIsToBeEffected + Input**(`createBookInput`) convention for naming inputs

As one can see in our above example `createBookInput` is Input object type and `Book` is Output object type which defines the output of our createBook mutation. More on mutation later in this blog. This way we are returning out Book after creating it and maybe persisting it in our database. so, we're no also able to efficiently update our cache on the client side. Its generally good practice to return our mutated data(that is created, deleted or updated) after mutation. Its important to notice that we have used a non-null(`!`) modifier for input. So, if the input argument some turns out to be passed as null then our GraphQL service errors out.

## Interfaces and Unions
GraphQL specification mentions two abstract types namely
- Interfaces
- Unions

Below we'll look at why abstract types are used and how to implement them. Abstract types greatly improve GraphQL schema and simplify queries and mutations

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

As said by the specification above Interfaces are usually needed when we are looking to access certain fields of objects that have to comply to the properties defined by the interface. These set of fields can be included by multiple object types. for example consider the below example we can abstract out the type `Book` to interface as follows

```graphql
interface Book {
  title: String
  author: Author
}

type TextBook implements Book {
  title: String # Must be present
  author: Author # Must be present
  course: Course
}

type Comic implements Book {
  title: String # Must be present
  author: Author # Must be present
  genre: String
}

type Query {
  myBooks: [Book] # list of Book
}
```
As we can see above every type that implements our interface `Book` also have the same fields in common(`title`, `author`). These fields also need to be explicitly written for each type implementing the interface. Now if you see this gives us one greatest advantage to use interface is that it allows us to access a group of types in one single entity leading to much cleaner schema design, as well as reducing the complexity

In the above example `Query.myBooks` returns a list that include both `TextBook` and `Comic` as well. lets look at how clients can query on fields and subfields that are and are not included in interface.

```graphql
query {
  myBooks {
    title   # always present part of Book interface
    author  # always present part of Book interface
    ...on TextBook {
      course: { # only present on type TextBook
        name
      }
    }

    ...on Comic {
      genre # only present on type Comic
    }
  }
}
```
This query uses [inline fragments](https://graphql.org/learn/queries/#inline-fragments) to fetch a `Book`'s `course` if it is `TextBook` and `genre` if it is of type `Comic`.

### Unions
Above we saw what interfaces are, how we can abstract out the common field on different types. what if we wish to apply similar kind of abstraction to type that do not have any common fields? For `Book` interface for example, we assumed that for every type that implement interface `Book` have `title` and `author` in common. But lets consider two types that have no fields in common and will not wish to add any such constraints on children types. Unions are great to represent such types, We just have to represent multiple types that do not have any fields in common. Lets look at a example

```graphql
type Movie {
  name: String
  director: String
}

union SearchResult = Book | Movie

query {
  search(contains: String!): [SearchResult]
}
```
The `SearchResults` union enables `Query.search` to return a list that includes both `Book` and `Movie` types, So clients can again make use of inline fragments to query fields on union as below

```graphql
query {
  search(contains: "Godfather") {
    ... on Book {
      title
    }
    ... on Movie {
      name
    }
  }
}
```
Interfaces and union types are the only abstract types available in GraphQL, these types can be wisely used to reduce the complexity of our schema, number of queries and mutations and also describe data much better in a precise way. [This issue](https://github.com/graphql/graphql-spec/issues/236) on GitHub might be helpful to further clarify the difference between Interface and Unions and how they are meant for different use cases.

## Modifiers
As we already know by now that Object types, scalars and enums are the only kind of types that we can define in GraphQL, When we use those types in our schema or during input type declaration or so, we can also apply additional type modifiers that affect validation of those values. In simple a Modifier modifies the type to which they refer to allowing use to add validations to that type. There are two type of modifiers in GraphQL they are
- List
- Non-Null

### List
A GraphQL list is a special collection type which declares the type of each item in the List of specified type. List values are serialized as ordered lists. GraphQL list represent a collection of values, we can relate these to arrays, However this analogy is not completely precise. List modifiers are represented through a pair of squared brackets wrapped around the instance of some type.
for example as we defined above

```graphql
type Query {
  myBooks: [Book] # list of Book
}
```
we specified that the query `myBooks` will return a list of Books, with each book of type `Book`. This is exactly how list modifiers can be used to modify output type to return a list of particular object type.

### Non-Null
Non-Null allows us to add additional type of validation. In GraphQL SDL it is represented by `!` (exclamation mark) after the type name. By marking it as Non-Null we are guaranteeing that our server always expects Non-Null value for this field, And some how if this type ends up as null value then that will throw up an execution error, letting client know that something is not right!.

for example as shown above

```graphql
type Book {
  title: String!
  pages: Int!
}
```
The above example states that `title` and `pages` cannot be null and a type is also assigned, it represents that the field `title` cannot be null and cannot be of type other than `String` thus giving us strict validations on fields.

Non-Null type modifier can also be used with input types, which will cause GraphQL to return a validation error if null is passed as that input argument.

```graphql
input createBookInput {
  title: String!
  pages: Int!
}
mutation createBook(input: createBookInput!): Book!
```
If any of field in the above input argument to the `createBook` provided by the client turns out to be null then our GraphQL service error out.

### Composing Modifiers

We can also compose our Non-Null modifiers with List modifiers to create a special type modifiers with combining validation powers from both types. This gives pretty powerful validations, lets look at an example below

```graphql

# 1. List of Non-Null types
nickNames: [String!]
# This means the list nickNames can itself be null but cant have null members i.e
nickNames: [] # valid
nickNames: null # valid
nickNames: ["Bruno", "B" ] # valid
nickNames: ["Bruno", null] # not valid, error!

# -----------
# 2. Non-Null List of types

nickNames: [String]!
# This means the list nickNames cannot be null but can have null members and can be empty i.e
nickNames: null # not valid, error!
nickNames: [] # valid
nickNames: ["Bruno", "B" ] # valid
nickNames: ["Bruno", null] # valid


# -----------
# 3. Non-Null List of Non-Null types

nickNames: [String!]!
# This means the list as well as it's members cannot be null 
nickNames: null # not valid, error!
nickNames: [] # valid
nickNames: ["Bruno", "B" ] # valid
nickNames: ["Bruno", null] # not valid, error!

```

As seen above with modifiers we are able to add special behaviors to our GraphQL types and schemas. Modifiers are a great tool to make strict and elegant GraphQL schemas.

> 📚 Further learning resources
>
> - https://www.howtographql.com/basics/2-core-concepts/
> - https://graphql.org/learn/schema/
> - [GraphQL specs](https://spec.graphql.org/June2018/)

👉 This blogpost was originally publish at my personal [blog site](https://jaygurav.netlify.app/graphql/graphqlTypesSystem/)

### Get in touch
Hey, have any suggestions, questions or concerns, You can find me [Twitter](https://twitter.com/JayMGurav), [GitHub](https://github.com/jaymgurav/) and [LinkedIn](https://www.linkedin.com/in/jaymgurav). Help me make this better!, Feel free to drop me a message and I’ll get back to you soon Thanks!🎉