Generate Javascript static types from GraphQL: TypeScript and Flow
Tags: react, javascript, typescript, node
Published: 2020-01-20 09:12:17

---
title: Generate Javascript static types from GraphQL: TypeScript and Flow
published: true
description: How to generate Javascript (Flow and TypeScript) types automatically from GraphQL schema. How to generate Javascript static types for React and your GraphQL resolvers.
tags: react, javascript, typescript, node
canonical_url: https://atheros.ai/blog/generate-javascript-static-types-from-graphql-typescript-and-flow
---

## Introduction

Javascript is usually considered as an **untyped** or **weakly-typed** language. I will not go into the discussion about this topic in this article. You can check out for example this <a title="Javascript typed vs weakly typed" href="https://stackoverflow.com/questions/964910/is-javascript-an-untyped-language">StackOverflow thread</a> for more information. We currently cannot prove the correlation between using statically/dynamically typed languages and number of defects in the system, but there are some evidences that errors occur less when using statically typed language. You can go more deeply into the topic in the following <a href="http://web.cs.ucdavis.edu/~filkov/papers/lang_github.pdf">study</a>. In addition statically typed languages can offer smart tooling integrated in your IDE, which enables you to perform more complex autocompletion and linting. Javascript is one of the most widely spread and demanding language. You can use it for frontend, backend or even mobile development. Javascript has definitely a lot of advantages, but as it is **untyped** it does not support static typings by default. Fortunately, we can enhance the **Javascript** language using the following tools to add static typings to our project:

* **<a title="TypeScript homepage" href="https://www.typescriptlang.org/">TypeScript</a>**
* **<a title="Flow homepage" href="https://flow.org/">Flow</a>**

**Flow** is open-sourced by **Facebook** and we are able to perform type checking with a **Flow** server while coding. On the other hand, **TypeScript** is maintained by **Microsoft**. **TypeScript** is older then **Flow** and seems to me that the ecosystem is much better. **TypeScript** has better support with typings for more libraries, especially on the backend. In this article we will use solely TypeScript in our examples.

## Model example of manual static typing for GraphQL queries

Let’s first take a look at how to define our static typings manually. We will start with this simple schema:

``` graphql
type Subscription {
  id: ID!
  email: String!
}

input SubscribeInput {
  email: String!
}

type Mutation {
  subscribe(input: SubscribeInput!): Subscription!
}

type Query {
  subscriptions: [Subscription]
}
```

We would like to fetch the list of subscribed users. If you have your development server running you can move to <a title="GraphQL Playground" href="http://localhost:3000/graphql">GraphQL Playground</a>. We can then execute the following GraphQL document:

``` graphql
query getSubscriptions {
  subscriptions {
    id
    email
  }
}
```

Now if you use our <a href="https://github.com/atherosai/next-react-graphql-apollo-hooks" title="Example repository">example repository</a>. Let's say we would like to include generate our **TypeScript** types each time we change our GraphQL schema and propagate these changes to your development workflow, so that you can use it directly in your frontend components
We can execute this query in <a href="https://github.com/prisma/graphql-playground" title="GraphQL playground">GraphiQL</a> and we will receive something like this

``` json
{
  "data": {
    "subscriptions": [
      {
        "id": "02b7d240-0d44-11ea-bbff-1b2383f1b30b",
        "email": "david@atheros.ai"
      }
    ]
  }
}
```

Then we will start writing our **TypeScript** type definitions. We will first need to manually check the schema so that our definitions are in sync with the data from the GraphQL server. We can write the definition for **Subscriptions query** as follows:

``` typescript
export interface Subscribe {
  id: string;
  email: string;
}

export interface GetSubscriptions {
  subscriptions: Subscribe[];
}
```

We need to manually check our schema to see what each type represents so that our static typings are in sync. Let’s say we want to add the required field **source** that will be typed as a <a href="/blog/how-to-use-graphql-enum-type-and-its-best-practices" title="How to build GraphQL enums">enum value</a>. The updated **Subscription** type in **SDL** (Schema Definition Language) will then be as follows:

``` graphql
enum SourceEnum {
  ARTICLE
  HOME_PAGE
}

type Subscription {
  id: ID!
  email: String!
  source: SourceEnum!
}
```

In order to fetch this field we will need to update our **GraphQL** query as well:

``` graphql
query getSubscriptions {
  subscriptions {
    id
    email
    source
  }
}
```

But what about our typings? We need to update the affected typings wherever they are being used. I believe that the biggest trade off for static typing is the increased time for development, the duplication of data structure and the possible friction that can occur with versioning our **APIs**. We cannot only update our code; we also need to add our typings manually and then update them after each change. It can lead to wrong typings and false errors if developers do not sync up immediately. These problems can be solved with **automatic generation of types** with GraphQL. Our **GraphQL gateway** will serve as our single source of truth, and static typing will be synced immediately on both the frontend and backend.

## How would we achieve that with GraphQL?
So now that we have talked about adding typings in our **TypeScript** code manually, how can **GraphQL** help us automate that? As we mentioned, one of the biggest problems when defining typings is that the manual static typing can get too time-consuming and it is hard to keep everything in sync through versioning. We could already notice the connection between **GraphQL** type system and either the **TypeScript** or **Flow** type systems. GraphQL’s type system is strongly typed, and we can perform transformations from **GraphQL** type system to **TypeScript** type systems.

To get a better idea of how this works in practice let’s visualize how to transform the GraphQL types into **TypeScript** types. First let’s take a look at this graph

![Type transformations](https://thepracticaldev.s3.amazonaws.com/i/5a587dk2bbd1qu3imzkz.png)

We will first define our GraphQL schema on our server. Then we need to generate static typings on the frontend to type the results and arguments for queries and mutations. We also need to generate separate **static typings on the backend** for our resolvers. Every time our GraphQL schema changes we also need to update our affected static typings. The GraphQL gateway is now the single source of truth for typings, but in order to remove the friction between definitions we need to introduce automation. This way we will not have to keep everything in sync manually.

## Generating types on the frontend with <a href="https://graphql-code-generator.com/" title="GraphQL CodeGen">GraphQL CodeGen</a>

Let’s generate **TypeScript** types for our responses from the **GraphQL** server. We will use a library called <a href="https://graphql-code-generator.com/" title="GraphQL CodeGen">GraphQL CodeGen</a>.

We will use our <a title="Example repository" href="https://github.com/atherosai/next-react-graphql-apollo-hooks">example repository</a>.
In order to execute the code you can clone the repository with

``` bash
git clone git@github.com:atherosai/next-react-graphql-apollo-hooks.git
```

install dependencies with

``` bash
npm i
```

and start the server in development with 

``` bash
npm run dev
```

## GraphQL CodeGen yaml file

GraphQLCodeGen works on modular bases. There is a lot of plug-ins that enables you apply GraphQL CodeGen library to many different applications. For now we will use just two plug-ins

* **TypeScript operations plugin**: enables to generate types for mutations and queries
* **TypeScript plugin**: generate basic types from the schema

``` yaml
schema: 'server/schema/typeDefs.ts'
documents: 'components/**/*.graphql'
generates:
  generated/typescript-operations.ts:
    - typescript-operations
    - typescript
```

We can see that we need to first define a way how to retrieve the information about the **schema**. This is done in the **schema** field and in our case we used typeDef file, where schema in SDL is written. GraphQLCodeGen will then apply <a href="/blog/graphql-introspection-and-introspection-queries" title="GraphQL schema introspection">schema introspection</a> and uses the results to generate TypeScript types. 
If your GraphQL server is running on port **3000**, you can also perform <a href="/blog/graphql-introspection-and-introspection-queries" title="GraphQL introspection and introspection queries">introspection</a> directly on the <a href="http://localhost:3000/graphql">endpoint</a>. Please note that for <a href="/blog/graphql-security-in-node-js-project" title="Security">security purposes</a> you should disable introspection in production; it should therefore only work in a development environment. 
We have also defined our **path to GraphQL documents**. In the example repository we store our GraphQL queries and mutations at our React component and the pattern above will validate all of them against our GraphQL schema and then generate TypeScript types for frontend. The last lines in the our GraphQLCodeGen config defines **output path of the generated types** and **plug-ins used**.

If you have installed **graphql-codegen** globally and you are in the folder of our example repository you can just execute:

``` bash
graphql-codegen
```

otherwise you can use our npm script command:

``` bash
npm run gen:schema
```


This command will run a <a href="https://gist.github.com/a7v8x/c30d92d2ca2458035aadc41702da367d" title="GraphQL schema introspection query">schema introspection query</a>, take every **\*.graphql** file that matches the specified pattern and validate it with our GraphQL schema. Based on each GraphQL file we will generate a new **TypeScript** types.


## TypeScript output and how to use it in your React components

GraphQLCodeGen generated **.ts**, **.d.ts** files with types for each ***.graphql** requests into <a title="Generated folder for client" href="https://github.com/atherosai/next-react-graphql-apollo-hooks/tree/master/__generated__">__generated__</a> folder and we are able to import them into our *React-Apollo* components. Please note that for the sake of simplicity we did not implement *React* components in the repository. If you would like to generate *Flow* types or other supported types you can only change *--target* parameter. The following *TypeScript* file for the *getUsers query* should now be available in the *queries/__generated__*

``` javascript
export type Maybe<T> = T | null;
export type SubscribeMutationVariables = {
  input: SubscribeInput
};


export type SubscribeMutation = (
  { __typename?: 'Mutation' }
  & { subscribe: (
    { __typename?: 'Subscription' }
    & Pick<Subscription, 'id' | 'email' | 'source'>
  ) }
);

export type SubscriptionsQueryVariables = {};


export type SubscriptionsQuery = (
  { __typename?: 'Query' }
  & { subscriptions: Maybe<Array<Maybe<(
    { __typename?: 'Subscription' }
    & Pick<Subscription, 'id' | 'email' | 'source'>
  )>>> }
);

/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string,
  String: string,
  Boolean: boolean,
  Int: number,
  Float: number,
};

export type Mutation = {
   __typename?: 'Mutation',
  subscribe: Subscription,
};


export type MutationSubscribeArgs = {
  input: SubscribeInput
};

export type Query = {
   __typename?: 'Query',
  subscriptions?: Maybe<Array<Maybe<Subscription>>>,
};

export enum SourceEnum {
  Article = 'ARTICLE',
  HomePage = 'HOME_PAGE'
}

export type SubscribeInput = {
  email: Scalars['String'],
  source: SourceEnum,
};

export type Subscription = {
   __typename?: 'Subscription',
  id: Scalars['ID'],
  email: Scalars['String'],
  source: SourceEnum,
};
```

I believe that the best way to operate is to generate type definitions every time you change your GraphQL schema. This will make your types up-to-date and you will avoid mismatches on your frontend. Now let's use our generated types for our React components in the <a href="https://github.com/atherosai/next-react-graphql-apollo-hooks" title="Repository with examples">repository</a>.
In our project we have one query for fetching subscriptions

``` graphql
query getSubscriptions {
  subscriptions {
    id
    email
    source
  }
}
```

On the client we are rendering our results in the table with two columns **email** and **source**. We use <a href="/blog/react-hooks-in-apollo-client-for-graphql-queries-and-mutations" title="How to implement React Hooks in Apollo client">Apollo client and React Hooks</a> for our data fetching. React component is written as follows:

``` javascript
import React from 'react';
import get from 'lodash.get';
import uuid from 'uuid/v1';
import { useQuery } from '@apollo/react-hooks';
import SUBSCRIPTIONS_QUERY from './SUBSCRIPTIONS.graphql';
import { SubscriptionsQuery, SubscriptionsQueryVariables } from '../../../__generated__/typescript-operations';
import s from './SubscriptionsTable.scss';

const SubscriptionsTable: React.FunctionComponent = () => {
  const { data, loading, error } = useQuery<SubscriptionsQuery,
  SubscriptionsQueryVariables>(SUBSCRIPTIONS_QUERY);

  if (loading) return <>Loading...</>;
  if (error) return <>{`Error! ${error.message}`}</>;

  return (
    <div className={s.SubscriptionTable}>
      <table>
        <thead>
          <tr>
            <th>Email</th>
            <th>Source</th>
          </tr>
        </thead>
        <tbody>
          {data && data.subscriptions && data.subscriptions.map((subscription) => (
            <tr key={get(subscription, 'id', uuid())}>
              <td>
                {get(subscription, 'email')}
              </td>
              <td>
                {get(subscription, 'source')}
              </td>
            </tr>
          ))}
        </tbody>
      </table>

    </div>
  );
};

export default SubscriptionsTable;
```

Apollo client is written in TypeScript so it has good support for handling your types. We are passing our generated types in the **useQuery** hook.
Our second GraphQL operation is **subscribe** mutation. Our component is written as follows:

``` javascript
/* eslint-disable jsx-a11y/label-has-for */
import React from 'react';
import { useMutation } from '@apollo/react-hooks';
import {
  Formik, ErrorMessage, Form, Field,
} from 'formik';
import * as Yup from 'yup';
// eslint-disable-next-line import/no-extraneous-dependencies
import { FetchResult } from 'apollo-link';
import get from 'lodash.get';
import s from './Subscription.scss';
import SUSCRIBE_MUTATION from './SUBSCRIBE.graphql';
import SUBSCRIPTIONS_QUERY from '../SubscriptionsTable/SUBSCRIPTIONS.graphql';
import { SubscribeMutation, SubscribeMutationVariables, Query } from '../../../__generated__/typescript-operations';

interface InitialValuesI {
  email: string;
}
interface HandleSubscribeI {
  values: InitialValuesI;
  subscribeMutation: Function;
  resetForm: Function;
}


const handleSubsribe: Function = async ({
  values,
  subscribeMutation,
  resetForm,
}: HandleSubscribeI) => {
  const subscribeResult: Promise<SubscribeMutation> = await subscribeMutation({
    variables: {
      input: {
        source: 'HOME_PAGE',
        ...values,
      },
    },
  });

  if (get(subscribeResult, 'data.subscribe')) {
    resetForm();
  }

  return subscribeResult;
};


const Subscription: React.FunctionComponent = () => {
  const [subscribeMutation] = useMutation<SubscribeMutation, SubscribeMutationVariables>(
    SUSCRIBE_MUTATION,
    {
      update: (cache, { data }: FetchResult): void => {
        const dataResult = cache.readQuery<Query>({ query: SUBSCRIPTIONS_QUERY });
        cache.writeQuery({
          query: SUBSCRIPTIONS_QUERY,
          data: {
            subscriptions: dataResult
            && dataResult.subscriptions
            && dataResult.subscriptions.concat([data && data.subscribe]),
          },
        });
      },
    },
  );
  const initialValues: InitialValuesI = {
    email: '',
  };
  return (
    <div className={s.Subscription}>
      <div className={s.Subscription__SubscriptionWrapper}>
        <div>
          <h2>
            Lorem ipsum is place-holder text commonly used in the graphic, print, and publishing
            industries for previewing layouts and visual mock-ups.
          </h2>
          <Formik
            initialValues={initialValues}
            onSubmit={async (values, { resetForm }): Promise<SubscribeMutation> => handleSubsribe({
              values,
              subscribeMutation,
              resetForm,
            })}
            validationSchema={Yup.object().shape({
              email: Yup.string()
                .email()
                .required('Before submitting you need to provide your email'),
            })}
          >
            <Form>
              <div className={s.Subscription__Row}>
                <label htmlFor="email">Email</label>
                <Field
                  id="email"
                  className={s.Carousel__EmailInput}
                  name="email"
                  placeholder="your@email.com"
                  type="email"
                />
                <button type="submit" className={s.Subscription__SubscribeButton}>
                    Subscribe
                </button>
              </div>
              <div className={s.Subscription__FieldErrorRow}>
                <ErrorMessage
                  name="email"
                  component="div"
                  className={s.Subscription__FieldError}
                />
              </div>
            </Form>
          </Formik>
        </div>
      </div>
    </div>
  );
};

export default Subscription;
```

In this case we used **useMutation hook** and again passed our generated types into useMutation function. These steps enabled us to use generated types on the client and each time we will change our GraphQL schema we will get up to date TypeScript suggestions.

## Generating typed-safe resolvers on your server with <a title="Automatic code generation with GraphQLCodeGen" href="https://github.com/dotansimha/graphql-code-generator">GraphQLCodeGen</a>

In order to generate server-side typings for your resolvers we need to use <a title="TypeScript resolver plugin" href="https://graphql-code-generator.com/docs/plugins/typescript-resolvers">additional plugin</a>. After updating our **codegen.yaml** we will get the following:

``` yaml
schema: 'server/schema/typeDefs.ts'
documents: 'components/**/*.graphql'
generates:
  __generated__/typescript-operations.ts:
    - typescript-operations
    - typescript
  server/__generated__/resolver-types.ts: 
    - typescript
    - typescript-resolvers
```

We can generate our types again with:

``` bash
npm run gen:schema
```

Now we have generated also types for our resolvers to **server/__generated__/resolver-types.ts**. We can now type all of our resolvers as follows:

``` javascript
import { getSubscriptions, createSubscription } from '../requests/subscription-requests';
import { Resolvers } from '../__generated__/resolver-types';


interface StringIndexSignatureInterface {
  [index: string]: any;
}

type StringIndexed<T> = T & StringIndexSignatureInterface

const resolvers: StringIndexed<Resolvers> = {
  Query: {
    subscriptions: () => getSubscriptions(),
  },
  Mutation: {
    subscribe: async (__, args) => createSubscription({}, args),
  },
};

export default resolvers;
```

## How to take it even further?

But what about not just generating static types? What about generating your own code? This is something the **GraphQLCodeGen** library can also accomplish with plug-ins. For our project the most relevant plugin is for <a href="https://graphql-code-generator.com/docs/plugins/typescript-react-apollo" title="React Apollo plugin">React Apollo</a>.
This can help you to skip one additional manual step of creating React Apollo components for mutations and queries.

## Summary

I believe that automatic type and code generation is one of the biggest trends in **GraphQL** ecosystem. We are having great ecosystem for development especially for **TypeScript** and **GraphQLCodeGen**. You can use our <a title="Code generation from GraphQL starter project" href="https://github.com/atherosai/next-react-graphql-apollo-hooks">starter project</a> to speed up your set-up. This will help you diminish unnecessary friction between your static typing on the frontend with the **GraphQL API**. You can inject the command to regenerate types after each change in your GraphQL schema files. This way you will have your types automatically in sync with your API. A further advantage is that no extra communication between backend and frontend team members is required, since frontend engineers are notified about the changes in their types. We are additionally able to validate your queries and mutations in CI to avoid deploying queries and mutations on the frontend that do not comply to the current **GraphQL** schema. There is definitely space for improvement in libraries, especially for server side typings, but current implementations using <a title="Automatic code generation with GraphQLCodeGen" href="https://github.com/dotansimha/graphql-code-generator">GraphQLCodeGen</a> is a promising step for more efficient work-flows. I believe that automatic type generation of static types using GraphQL not only in **TypeScript** has a bright future. It will allow us to spend less time writing boilerplate code and updating our types and more time on shipping high-quality typed products.

> Originally published at https://atheros.ai/blog/generate-javascript-static-types-from-graphql-typescript-and-flow

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