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.
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.
Perfect! With this GraphQL version of the OpenWeatherMap API, we can now auto-generate some code for a TypeScript application using GraphQL Code Generator.
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.
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!