Input object type as an argument for GraphQL mutations and queries
Tags: webdev, graphql, react, node
Published: 2020-02-03 14:28:01

---
title: Input object type as an argument for GraphQL mutations and queries
published: true
description: In the previous article, we talked about the basic set-up for GraphQL projects as well as the use of GraphiQL for executing queries and mutations. With this knowledge, we can now dive deeper into the world of GraphQL input types. GraphQL is a query language, which can be used with different languages like Javascript, C#, Scala, and more. However, in this article, we will focus on Facebook's Javascript implementation of GraphQL called graphql-js.
tags: webdev, graphql, react, node
canonical_url: https://atheros.ai/blog/input-object-type-as-an-argument-for-graphql-mutations-and-queries
---

## Introduction

In the <a title="Setting up basic GraphQL server" href="https://medium.com/atheros/setting-up-basic-graphql-server-in-node-js-with-express-c25eeaa819c2">previous article</a>, we talked about the basic set-up for GraphQL projects as well as the use of GraphiQL for executing queries and mutations. With this knowledge, we can now dive deeper into the world of GraphQL input types. GraphQL is a query language, which can be used with different languages like Javascript, C#, Scala, and more. However, in this article we will focus on Facebook's Javascript implementation of GraphQL called <a  title="Graphql Javascript library" href="https://github.com/graphql/graphql-js">graphql-js</a>. We will also introduce some code snippets and examples illustrating how different types can be written in the GraphQL schema language. This is not language-specific, however, and the main focus will be on designing a GraphQL schema using the graphql-js classes. We will concentrate on the often misunderstood topic of using GraphQL input object types in mutations.

## Input and output types

According to <a title="GraphQL specification" href="https://facebook.github.io/graphql/">GraphQL specification</a>, when we deal with its type system, we have to discuss two different categories of types:
* **output type** can be used for definition of data, which is obtained after query execution;
* **input types** are used as a query parameters, e.g., payload for creating a user.
In graphql-js library we basically have two different types, which can be used as objects. **GraphQLObjectType** (an output type), and **GraphQLInputObjectType** (an input type).

## Designing our mutation


Now let's consider creating a schema for saving users into a database. We will not use a real database, as it is not the main focus of our article. The **in memory** database is good enough for us to get started. For more information, please check out <a title="Input object as an argument for GraphQL mutations"  href="https://github.com/atherosai/graphql-gateway-apollo-express">this repository</a> on my GitHub account, where the in-memory database is implemented. You can quickly start with this command
``` bash
git clone git@github.com:atherosai/graphql-gateway-apollo-express.git
```
The types in the schema have some additional fields than in the following examples, but it still illustrates all the concepts precisely. We can start building a schema by defining the data structure. In GraphQL this means defining our GraphQL types, which we can do using the **GraphQLObjectType** from the graphql-js library. By defining the GraphQLObjectType and also a corresponding query or mutation, we can then query for desired fields to retrieve from the database. When we query a field in GraphQL, we are basically asking for a unit of data. Each field can be a scalar type or an enum type. A field is also sometimes called a leaf, a name from graph theory related to tree graphs.
To create a new instance of GraphQLObjectType in graphql-js we have to use at least some of these parameters:
* **name*** - Each name of an object type has to be unique across the schema;
* **fields*** - Fields can be an object with field definitions or a function, which returns an object with field definitions. Each field must have a type definition, and the other optional attributes are description and default values. An object has to have at least one field;
* **description** - This is an optional attribute, but is really useful for GraphQL schema documentation.

Now let's try to create a simple **User** Object with the following fields: **id**, **username**, **email**, **phone**, **role**, **firstName**, **lastName** and two timestamps **createdAt** and **updatedAt**.
``` javascript
import {
  GraphQLString,
  GraphQLID,
  GraphQLObjectType,
  GraphQLNonNull,
} from 'graphql';

const User = new GraphQLObjectType({
  name: 'User',
  description: 'User type definition',
  fields: () => ({
      id: {
          type: new GraphQLNonNull(GraphQLID),
      },
      username: {
          type: new GraphQLNonNull(GraphQLString),
      },
      email: {
          type: GraphQLString,
      },
      phone: {
          type: GraphQLString,
      },
      firstName: {
          type: GraphQLString,
      },
      lastName: {
          type: GraphQLString,
      },
  }),
});

export default User;
```
It can be also written in SDL
``` graphql

"""User type definition"""
type User {
  id: ID!
  username: String!
  email: String
  phone: String
  firstName: String
  lastName: String
}

```
Both ways of defining our type offer their own advantages and disadvantages. However, If you want to use the Schema Definition Language for more complex schema, it is better to use some third party tool like <a  title="GraphQL tools Apollo" href="https://github.com/apollographql/graphql-tools">graphql-tools</a>. More information can be found, for example, in <a title="GraphQL tools Apollo" href="http://dev.apollodata.com/tools/graphql-tools/index.html">Apollo docs</a> or in some of other articles. Now let’s consider designing a mutation for adding users. If you do not use <a title="Relay.js" href="https://facebook.github.io/relay/">Relay</a>, the query string for executing this mutation may look like this:
``` graphql
mutation {
  createUser(email: "david@atheros.ai", firstName: "David", lastName: "Mráz", phone: "123456789", username: "a7v8x") {
    user {
      id
      username
      firstName
      lastName
      email
      phone
    }
  }
}
```
The parameters passed into a **createUser()** are called <a title="GraphQL arguments"  href="https://facebook.github.io/graphql/#sec-Language.Arguments">**arguments**</a>. All the fields we are asking for is then called <a title="Selection set"  href="https://facebook.github.io/graphql/#sec-Selection-Sets">selection set</a>. An argument, for example, could be a scalar argument like GraphQLString or also GraphQLInputObjectType from the <a title="GraphQL reference implementation"  href="https://github.com/graphql/graphql-js">graphql-js</a> library. The mutation above can be written in our schema in the following way:
``` javascript
import {
  GraphQLList,
  GraphQLNonNull
} from 'graphql';
import { isEmail } from 'validator';
import { createUser } from '../../operations/users-operations';
import CreateUserPayload from "./CreateUserPayload";

const UserMutations = {
  createUser: {
      type: CreateUserPayload,
      args: {
          username: {
            type: new GraphQLNonNull(GraphQLString),
          },
          email: {
            type: GraphQLString,
          },
          phone: {
            type: GraphQLString,
          },
          firstName: {
            type: GraphQLString,
          },
          lastName: {
            type: GraphQLString,
          },
      },
      resolve: async ({}, { input }) => {
          if (input.email && !isEmail(input.email)) {
              throw new Error('Email is not in valid format');
          }
          return createUser(input);
      },
  },
}

export default UserMutations;
```
We can see that we do not want to pass the id, as the server generates an id for every new user. In resolver, we have added a simple email validation function for new user emails using a library called <a title="Validator.js Github"  href="https://github.com/chriso/validator.js">validator js</a>. The email validation can be also done by defining the custom scalar type. For simplicity’s sake, we’ll leave that to another article. As for the mutation arguments, if you do not use some static type checking like Flow, this can lead to different errors, as a lot of arguments have to be specified. For these reasons, it is not considered a good practice. This problem can be solved with the so-called <a title="Parameter object pattern"  href="http://wiki.c2.com/?ParameterObject">**parameter object pattern**</a>. The solution is to replace a lot of arguments with an input object and then we can only reference the input object and access its properties with dot notation. This pattern is enforced in Relay by default. It is commonly considered a best practice to use an object, called input, as an argument for the specific mutation. I would recommend not only using it in Relay, but also in Apollo or just any other schema that does not us a GraphQL client. The need for the use of this pattern increases with the number of arguments. However, it is good to follow this practice in every mutation.

## Applying parameter object pattern on our mutation

Now let’s apply parameter object pattern on our **createUser** mutation. First, we need to define the **UserInput**, which can be used as a parameter object for the mutation. This code accomplishes this goal
``` javascript
import {
  GraphQLString,
  GraphQLInputObjectType,
  GraphQLNonNull,
} from 'graphql';

const CreateUserInputType = new GraphQLInputObjectType({
  name: 'CreateUserInput',
  description: 'Input payload for creating user',
  fields: () => ({
    username: {
      type: new GraphQLNonNull(GraphQLString),
    },
    email: {
      type: GraphQLString,
    },
    phone: {
      type: GraphQLString,
    },
    firstName: {
      type: GraphQLString,
    },
    lastName: {
      type: GraphQLString,
    },
  }),
});

export default CreateUserInputType;
```
or again in SDL:
``` graphql
input CreateUserInput {
  username: String!
  email: String
  phone: String
  firstName: String
  lastName: String
}
```
You may ask yourself, why do I need to have two different types of input and output? Isn’t it possible to just use GraphQLObjectType on both arguments and field definitions? The reason is that GraphQL needs two different structures. One is for taking input values and coercing them into server-side values, and the other is responsible for fetching data from a server. If we have these two types together, the type has to implement both of these structures. This problem is also discussed in <a title="Input object"  href="http://facebook.github.io/graphql/#sec-Input-Objects">GraphQL specification</a>

> The Object type defined above is inappropriate for re‐use here because 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 a separate type in the system.

Another difference is also, that **GraphQLNonNull**, basically responsible for not allowing null values in the query, has a different meaning. When it comes to **GraphQLObjectType**, if we query for the field in the object, the return value from the resolver function has to do two things. It needs to contain the field with the correct attribute, and it cannot be equal to null. As for input types, we need to specify the field, wrapped by a **GraphQLNonNull** instance, even just to execute the mutation. You can also check out this thread. Nevertheless, it is possible to avoid the boilerplate, which occurs if you define the fields twice. In my projects, I often assign the fields, used in both **GraphQLObjectType** and **GraphQLInputObjectType**, to a specific object. These fields are then imported into each type using the object spread operator. However, you have to be able to avoid circular dependencies and other issues, which come up when designing a more complex schema using graphql-js. Now we have defined the **GraphQLInputObjectType**, so it is possible to replace our previous mutation with the following code

``` javascript
import {
  GraphQLList,
  GraphQLNonNull
} from 'graphql';
import { isEmail } from 'validator';
import { createUser } from '../../operations/users-operations';
import CreateUserInput from "./CreateUserInputType";
import CreateUserPayload from "./CreateUserPayload";

const UserMutations = {
  createUser: {
      type: CreateUserPayload,
      args: {
          input: {
              type: new GraphQLNonNull(CreateUserInput),
          },
      },
      resolve: async ({}, { input }) => {
          if (input.email && !isEmail(input.email)) {
              throw new Error('Email is not in valid format');
          }
          return createUser(input);
      },
  },
}

export default UserMutations;
```

We can observe some reduction in complexity. This does not have such a high impact if we just use GraphiQL for executing the mutation:
``` graphql
mutation createUser {
  createUser(input: {
      username: "test", 
      email: "test@test.cz", 
      phone: "479332973", 
      firstName: "David", 
      lastName: "Test"
    }) {
    user {
        id
        username
        email
        phone
        firstName
        lastName
    }
  }
}
```
However, in a real app we often use variables instead. When we pass the mutation variable **input** using some frontend GraphQL caching client like <a title="Apollo client github"  href="https://github.com/apollographql/apollo-client">Apollo</a>, <a title="Relay.js github"  href="https://facebook.github.io/relay/">Relay</a>, or even with some promise based HTTP client like <a title="Axios github repository"  href="https://github.com/mzabriskie/axios">Axios</a>, we can then benefit from reducing costly string building. We pass variables separately from the query document and also reduce the code significantly. If we do not have an input object, the query with variables looks like this:
``` graphql
mutation createUser($email: String, $firstName: String, $lastName: String, $phone: String, $username: String!) {
  createUser(email: $email, firstName: $firstName, lastName: $lastName, phone: $phone, username: $username) {
    user {
      id
      firstName
      lastName
      phone
      email
      username
    }
  }
}
```
Nevertheless, by rewriting the mutation with the parameter object pattern we can then write it in the following format and significantly simplify our code:
``` graphql
mutation createUser($input: UserInput!) {
  createUser(input: $input) {
    user {
      id
      firstName
      lastName
      phone
      email
      username
    }
  }
}
```
There is a big advantage of designing a mutation like this. We can reduce the complexity of the frontend code and follow best practices in our project. The importance of input types increases with the number of arguments we have in a mutation. However, we should use best practices even if the mutation payload has just one argument.


> Did you like this post? You can clone the <a title="Github repository" href="https://github.com/atherosai/graphql-gateway-apollo-express">repository with examples and project setup</a>. 
> Feel free to send any questions about the topic to <a href="mailto:david@atheros.ai" title="Contact">david@atheros.ai</a>.