How to Generate TypeScript Type Definitions and Code from GraphQL

How to Generate TypeScript Type Definitions and Code from GraphQL

Using GraphQL together with TypeScript can have huge advantages, as you can use your GraphQL schema to create TypeScript type definitions and even code that fetches data from the GraphQL server. This is incredibly powerful. Basically it means we can have TypeScript types that match our GraphQL types and operations. An important nuance is that TypeScript and GraphQL have a set of types. It might take a minute to understand, but these are different things, as GraphQL and TypeScript have a similar type system with slightly different nuances.

Roy Derks

Tech Author, Speaker and Entrepreneur

Using GraphQL with TypeScript has great benefits because you can use the GraphQL schema to create TypeScript type definitions and code to retrieve data from the GraphQL server. It’s incredibly powerful. Why is this? This actually means that you can have a TypeScript type that matches your GraphQL type and operation. One of the important nuances is that TypeScript has a typeset, and GraphQL has a typeset. It may take a minute to figure this out, but they are different because GraphQL and TypeScript have similar types of systems with slightly different nuances. In this article, I’ll show how to do use using the open-source library GraphQL Code Generator and a demo GraphQL API.

GraphQL API

To generate TypeScript type definitions and code from GraphQL, we first need to have a schema. For this, we’ll use a demo GraphQL server that we create using StepZen, a service to generate GraphQL APIs automatically, based on the free OpenWeatherMap API. To set up this GraphQL API, you need to follow the steps in this Github repository, including creating a free StepZen account.

When you’ve set up the GraphQL API, you can open the GraphiQL playground, in which you can use a query to get the weather report for a location. Let’s try this out by pasting the query below in the playground:

query GetWeatherReport {
  weatherReport(latitude: 38.897663, longitude: -77.036574) {
    description
    feelsLike
    latitude
    longitude
    temp
    units
    date
  }
}

Where the values for latitude and longitude are the coordinates for the White House in Washington D.C.

From the GraphiQL playground, this will result in a JSON response that consists of the weather report for the White House consisting of a description of the weather, the feeling temperature, and the actual temperature.

The GraphiQL playground with our query

The GraphiQL playground with our query

Perfect! With this GraphQL version of the OpenWeatherMap API, we can now auto-generate some code for a TypeScript application using GraphQL Code Generator.

Requesting GraphQL from your App

To get this data from the GraphQL API into our application, we need to run the query we’ve used above from our application. We can use either a standard HTTP request using fetch or a popular GraphQL client, like Apollo or urql for this.

For starters, let’s create a new React application using create-react-app that uses the TypeScript template by running:

npx create-react-app my-app --template typescript

Or using Yarn: yarn create react-app my-app --template typescript.

This example uses the library graphql-request. It’s very lightweight and requires only a few lines of code. It must be installed with npm or Yarn, together with the graphql library:

npm i graphql-request graphql

Or using Yarn: yarn add graphql-request graphql.

After installing it from npm, you can get the data from the GraphQL API by replacing the contents of src/App.tsx with the following:

// src/App.tsx
import { useEffect } from 'react';
import { GraphQLClient, gql } from 'graphql-request';

const STEPZEN_USERNAME = ''; // Insert your own
const STEPZEN_API_KEY = ''; // Insert your own

const query = gql`
  {
    weatherReport(latitude: 38.897663, longitude: -77.036574) {
      description
      feelsLike
      latitude
      longitude
      temp
      units
      date
    }
  }
`;

const graphQLClient = new GraphQLClient(
  `https://${STEPZEN_USERNAME}.stepzen.net/api/weatherreport/__graphql`,
  {
    headers: {
      authorization: `apikey ${STEPZEN_API_KEY}`,
    },
  },
);

function App() {
  useEffect(() => {
    graphQLClient.request(query).then((data: any) => console.log(data));
  }, []);

  return (
    <></>
  );
}

export default App;

The URL to reach the GraphQL API needs both your StepZen username and a name for the endpoint. This is generated when you create the GraphQL API using the CLI from StepZen.

We don’t do anything with this data yet, besides printing it into the console. Before displaying this data that we receive from the API, we should add type definitions for them. Instead of writing them manually, we let the GraphQL Code Generator library do this for us.

Using GraphQL Code Generator

You can use GraphQL Code Generator to generate type definitions and TypeScript code. This is a CLI tool that generates TypeScript types from any GraphQL scheme. Let’s build an application that gets information from the GraphQL API using TypeScript code generated from the GraphQL schema. To use GraphQL Code Generator, we need to install it first as a dev dependency, together with the plugin for TypeScript:

npm install --save-dev @graphql-codegen/cli @graphql-codegen/typescript

Or using Yarn: yarn add -D @graphql-codegen/cli @graphql-codegen/typescript.

We now have everything you need to generate a type definition from the GraphQL API.

However, to use the GraphQL code generator, you need to add a configuration file called codegen.yaml. This file specifies the URL of the GraphQL API and the plugin to use:

# codegen.yaml
schema: 
  - {{stepzen_api_endpoint}}:
      headers:
        Authorization: 'apikey {{stepzen_api_key}}'
generates:
  ./src/types.ts:
    plugins:
      - typescript

Instead of creating the configuration file manually, you can also use the CLI to generate the file for you. More info here.

After we’ve added the configuration file, a new command to run GraphQL Code Generator so it will create the TypeScript type definitions based on the contents of config.yaml. In the package.json file of the React application, this line can be added to the scripts field:

{
  "scripts": {
    "generate": "graphql-codegen"
  }
}

After adding the configuration file, you can run the command generate using npm or Yarn from the command line in the same directory where the configuration file was added. This will create a new file called src/types.ts that contains all the TypeScript type definitions based on the schema for the GraphQL API.

This means that you can use it to have the type definition for the data returned by graphql-request. This type definition can be added to the file src/App.tsx for the value of data:

import { WeatherReport } from './types';

function App() {
  useEffect(() => {
    graphQLClient
      .request(query)
      .then((data: WeatherReport) => console.log(data));
  }, []);

  return <></>;
}

export default App;

Pretty cool! Of course, there is much more you can do with GraphQL Code Generator, as you can find in their documentation. If you want to learn more about what you can do with TypeScript, React, or GraphQL? Please follow me on Twitter!

Read more here: Source link