GraphQL Types system

GraphQL Type System
Image from graphql.org

Type systems in GraphQL

As described in my article on Why GraphQL?, 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.

  • Object
  • Input Object
  • Union
  • Interfaces
  • List
  • Non-Null

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

{
user {
name
book: {
title
pages
}
}
}
//Would result in following JSON data{
“data”: {
“user”: {
“name”: “Jay”,
“book”: {
“title”: “Some book title”,
“pages”: 200
}
}
}
}
  1. custom scalars or user-defined scalars
  • 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

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

  • States through type system that a field will always be one of a finite set of values
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!
}

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

type Book {
title: String!
pages: Int!
}
  • Output types
input createBookInput {
title: String!
pages: Int!
}
mutation createBook(input: createBookInput!): Book!

Interfaces and Unions

GraphQL specification mentions two abstract types namely

  • Unions

Interfaces

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
}
query {
myBooks {
title # always present part of Book interface
author # always present part of Book interface
...on TextBook { # inline fragments
course: { # only present on type TextBook
name
}
}
...on Comic {
genre # only present on 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

type Movie {
name: String
director: String
}
union SearchResult = Book | Moviequery {
search(contains: String!): [SearchResult]
}
query {
search(contains: "Godfather") {
... on Book {
title
}
... on Movie {
name
}
}
}

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

  • 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.

type Query {
myBooks: [Book] # list of Book
}

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!.

type Book {
title: String!
pages: Int!
}
input createBookInput {
title: String!
pages: Int!
}
mutation createBook(input: createBookInput!): Book!

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

# 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 i.e
nickNames: null # not valid error
nickNames: [] # valid
nickNames: ["Bruno", "B" ] # valid
nickNames: ["Bruno", null] # not valid error

Get in touch

Hey, have any suggestions, questions or concerns, Feel free Mail me. You can also find me Twitter, GitHub and LinkedIn. Help me make this better drop me a message and I’ll get back to you soon Thanks!🎉

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Jay Gurav

Jay Gurav

Software Engineer, Front-end and Back-end developer, with interest in building scalable, highly efficient, resilient and user-friendly systems.