Constructing Types with the GraphQL Package
Tags: webdev, javascript, node, graphql
Published: 2021-01-25 01:44:30

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

We can create a simple GraphQL server with Express. To do this, we need the `express-graphql` and `graphql` packages.

In this article, we’ll look at how to add types that we can use to build a schema with the `graphql` package.

### Constructing Types

We can construct a schema programmatically with the `GraphQLSchema` constructor that comes with the `graphql` package.

Instead of defining `Query` and `Mutation` types using the schema language, we can create them as separate object types.

For example, we can write the following to create a type with the `graphql.GraphQLObjectType` constructor to create an object type programmatically:

```
const express = require('express');
const graphqlHTTP = require('express-graphql');
const graphql = require('graphql');
const userType = new graphql.GraphQLObjectType({
  name: 'User',
  fields: {
    id: { type: graphql.GraphQLString },
    name: { type: graphql.GraphQLString },
  }
});

let users = {
  '1': {
    id: '1',
    name: 'Jane'
  }
}

const queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    user: {
      type: userType,
      args: {
        id: { type: graphql.GraphQLString }
      },
      resolve: (_, { id }) => {
        return users[id];
      }
    }
  }
});

const schema = new graphql.GraphQLSchema({ query: queryType });

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));
app.listen(3000, () => console.log('server started'));
```

In the code above, we created the `userType` GraphQL data type by writing:

```
const userType = new graphql.GraphQLObjectType({
  name: 'User',
  fields: {
    id: { type: graphql.GraphQLString },
    name: { type: graphql.GraphQLString },
  }
});
```

The `name` field defines the name of our type and the `fields` object has the fields that we include with the type. We defined `id` and `name` both to have type `String` .

Then we define our `Query` type with:

```
const queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    user: {
      type: userType,
      args: {
        id: { type: graphql.GraphQLString }
      },
      resolve: (_, { id }) => {
        return users[id];
      }
    }
  }
});
```

In the code above, we defined the `name` of the type to be `Query` . The `fields` we include is the `user` field, which is of type `User` that we defined above.

Also, we specified that we have the String `id` as the argument with the `args` property.

Finally, we have a `resolve` property with the resolver to return what we want to return.

In this case, we want to return the `User` from the `users` object given the `id` passed into the argument.

Then when we make the following query:

```
{
  user(id: "1"){
    id
    name
  }
}
```

We get back:

```
{
  "data": {
    "user": {
      "id": "1",
      "name": "Jane"
    }
  }
}
```

since we have the following in the `users` object:

```
let users = {
  '1': {
    id: '1',
    name: 'Jane'
  }
}
```

We can do the same with mutations.

This is particularly useful is we want to create a GraphQL schema automatically from something else like a database schema. We may have a common format for something like creating and updating database records.

It’s also useful for implementing features like union types that don’t map to ES6 constructs.

### GraphQLUnionType

We can create union types with the `GraphQLUnionType` constructor.

To create a union type and use it in our app, we can use the `GraphQLUnionType` constructor as follows:

```
const express = require('express');
const graphqlHTTP = require('express-graphql');
const graphql = require('graphql');
class Dog {
  constructor(id, name) {
    this.id = id;
    this.name = name;
  }
};

class Cat {
  constructor(id, name, age) {
    this.id = id;
    this.name = name;
    this.age = age;
  }
};

const DogType = new graphql.GraphQLObjectType({
  name: 'Dog',
  fields: {
    id: { type: graphql.GraphQLString },
    name: { type: graphql.GraphQLString },
  }
});

const CatType = new graphql.GraphQLObjectType({
  name: 'Cat',
  fields: {
    id: { type: graphql.GraphQLString },
    name: { type: graphql.GraphQLString },
    age: { type: graphql.GraphQLInt },
  }
});

const PetType = new graphql.GraphQLUnionType({
  name: 'Pet',
  types: [DogType, CatType],
  resolveType(value) {
    if (value instanceof Dog) {
      return DogType;
    }
    if (value instanceof Cat) {
      return CatType;
    }
  }
});

let pets = {
  '1': new Dog('1', 'Jane'),
  '2': new Cat('1', 'Jane', 11),
}

const queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    pet: {
      type: PetType,
      args: {
        id: { type: graphql.GraphQLString }
      },
      resolve: (_, { id }) => {
        return pets[id];
      }
    }
  }
});

const schema = new graphql.GraphQLSchema({ query: queryType });

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));
app.listen(3000, () => console.log('server started'));
```

In the code above, we created the `Dog` and `Cat` classes to serve as models for our data.

Then we create the GraphQL `Dog` and `Cat` types as follows:

```
const DogType = new graphql.GraphQLObjectType({
  name: 'Dog',
  fields: {
    id: { type: graphql.GraphQLString },
    name: { type: graphql.GraphQLString },
  }
});
const CatType = new graphql.GraphQLObjectType({
  name: 'Cat',
  fields: {
    id: { type: graphql.GraphQLString },
    name: { type: graphql.GraphQLString },
    age: { type: graphql.GraphQLInt },
  }
});
```

We defined the `DogType` and `CatType` constants to define the `Dog` and `Cat` object types.

`Dog` has `id` and `name` fields and `Cat` has `id` , `name` , and `age` fields.

Then we defined the `Pet` union type, which is a union of `Dog` and `Cat` as follows:

```
const PetType = new graphql.GraphQLUnionType({
  name: 'Pet',
  types: [DogType, CatType],
  resolveType(value) {
    if (value instanceof Dog) {
      return DogType;
    }
    if (value instanceof Cat) {
      return CatType;
    }
  }
});
```

Note that we have an array of `types` and a `resolveType` method instead of the `resolve` method.

Then finally, we create our query type so that we can return a response to the user as follows:

```
const queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    pet: {
      type: PetType,
      args: {
        id: { type: graphql.GraphQLString }
      },
      resolve: (_, { id }) => {
        return pets[id];
      }
    }
  }
});
```

The `resolve` function gets the `pets` entry by `id` and returns it, and we specified that the `type` we return is the `PetType` .

Once we did that, we can make our query using inline fragments as follows:

```
{
  pet(id: "1"){
    __typename,
    ...on Dog {
      id
      name
    }
    ...on Cat {
      id
      name
      age
    }
  }
}
```

In the query above, we discriminated between the fields of `Dog` and `Cat` by using the `...on` operator. `__typename` gets the type of the object returned.

With that query, we should get:

```
{
  "data": {
    "pet": {
      "__typename": "Dog",
      "id": "1",
      "name": "Jane"
    }
  }
}
```

since we have a `Dog` instance with key `'1'` in `pets` .

On the other hand, if we make a query for `Pet` with ID 2 as follows:

```
{
  pet(id: "2"){
    __typename,
    ...on Dog {
      id
      name
    }
    ...on Cat {
      id
      name
      age
    }
  }
}
```

We get:

```
{
  "data": {
    "pet": {
      "__typename": "Cat",
      "id": "1",
      "name": "Jane",
      "age": 11
    }
  }
}
```

since we have a `Cat` instance as the object with key `'2'` in `pets` .

### Conclusion

We can create types with `GraphQLObjectType` constructor to create object types.

To create union types, we can use the `GraphQLUnionType` , then we have to resolve the type in the `resolveType` method by checking the type of the object and returning the right one.

We can query union types with inline fragments and check the type with `__typename` .