DocumentationConstructing Types

Constructing Types

GraphQL.js can construct a schema in code, from GraphQL schema language, or from schema language plus supplemental JavaScript config for behavior that SDL cannot represent directly, such as field resolvers, abstract type resolution, custom scalar coercion, and extension metadata.

When you are using the GraphQLSchema constructor to create a schema, instead of defining Query and Mutation types solely using schema language, you create them as separate object types. This can be a good fit when the schema is generated from JavaScript data structures or when you want native language composition to drive the schema shape.

For example, let’s say we are building a simple API that lets you fetch user data for a few hardcoded users based on an id. The same API can be written with code-first constructors or SDL.

import express from 'express';
import { createHandler } from 'graphql-http/lib/use/express';
import * as graphql from 'graphql';
 
// Maps id to User object
const fakeDatabase = {
  a: {
    id: 'a',
    name: 'alice',
  },
  b: {
    id: 'b',
    name: 'bob',
  },
};
 
// Define the User type
const userType = new graphql.GraphQLObjectType({
  name: 'User',
  fields: {
    id: { type: graphql.GraphQLString },
    name: { type: graphql.GraphQLString },
  },
});
 
// Define the Query type with inline resolver
const queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    user: {
      type: userType,
      // `args` describes the arguments that the `user` query accepts
      args: {
        id: { type: graphql.GraphQLString },
      },
      resolve: (_, { id }) => {
        return fakeDatabase[id];
      },
    },
  },
});
 
const schema = new graphql.GraphQLSchema({ query: queryType });
 
const app = express();
app.all(
  '/graphql',
  createHandler({
    schema: schema,
  }),
);
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');

When we use the GraphQLSchema constructor method of creating the API, the root level resolvers are implemented on the Query and Mutation types. With SDL, those resolvers are installed on the built Query and Mutation fields.

Programmatic construction can be particularly useful if you want to create a GraphQL schema automatically from something else, like a database schema, or if native JavaScript composition makes the schema easier to maintain. SDL is useful when you want schema language and schema-attached JavaScript behavior together.