TypedDocumentNode: the next generation of GraphQL and TypeScript

Dotan Simha
TypedDocumentNode: the next generation of GraphQL and TypeScript - The Guild Blog
Looking for experts? We offer consulting and trainings.
Explore our services and get in touch.

Using GraphQL and Typescript on the client just became a whole lot easier!

The GraphQL Code Generator project has been around for 3 years, and we are constantly keep working on it and listening to your feedback!

As we were working and thinking about the next major version of the codegen, we came up with a really awesome tool which didn’t require any breaking change!

So today, after successfully integrating this feature into few of our largest clients, we can proudly share it with you - TypedDocumentNode.

A new and easier way to enjoy and integrate GraphQL and Typescript on the client.

TypedDocumentNode is a development tool for creating fully typed DocumentNode objects. It means that just by passing the GraphQL query/mutation/subscription/fragment to a supporting GraphQL client library, you'll get fully-typed result and variables objects.

This is made possible by TypeScript type inference.

TL;DR

  • TypedDocumentNode is a great solution for having pre-compiled (DocumentNode) GraphQL operations with built-in support for TypeScript types.
  • No need to specify types manually in your application code, all types are inferred automatically from your operation object.
  • You can easily extend any GraphQL client library to support it, even without changing the library code.
  • You can integrate it to your project using these instructions

Client-side applications, TypeScript and GraphQL

The integration of GraphQL and TypeScript in client-side applications has evolved in recent times:

2016: Manual Typings

We started with manually writing TypeScript types for our operations. It worked, but it didn't scale. It needed maintenance to make sure our types matched the exact selection set we are fetching.

2017: Generated Types

We moved to generated TypeScript types, with the power of GraphQL Code Generator - using @graphql-codegen/typescript and @graphql-codegen/typescript-operations plugins.

It's simpler (no need to maintain the types manually) but it requires us to manually specify the types each time we use the query.

2018: Generated Code

The next step of that evolution was to generate code - that means that we can generate React Hooks (@graphql-codegen/typescript-react-apollo or @graphql-codegen/typescript-urql), Angular Services (@graphql-codegen/typescript-apollo-angular) and much more. We can even generate a pre-compiled DocumentNode instead of dealing with Webpack loaders.

This generated code takes GraphQL and TypeScript to the next level - because we are getting ready-to-use code that has TypeScript types built-in and allow us to use it directly from our application code without the need to specify the types or GraphQL document manually:

2020: NEW TypedDocumentNode

Generating code is nice, but we don't always need to wrap hooks, services or similar code with more code. With the power of TypeScript, we can pre-compile the GraphQL operation into a DocumentNode, and add burn-in the TypeScript types.

With the support of the client-side libraries, we get automatic type inference and auto-complete - without generating additional code:

Live Demo

You can try it live here; note the autocomplete and automatic type inference for the result variable.

How does it work?

This project works in the following way:

  1. You write your GraphQL operations (query / mutation / subscription / fragment) in any way your prefer (for example - in a .graphql file).
  2. GraphQL Code Generator will generate a TypedDocumentNode for your operations (which is a bundle of pre-compiled DocumentNode with the operation result type and variables type).
  3. Instead of using your .graphql file, import the generated TypedDocumentNode and use it with your GraphQL client framework.
  4. You'll get automatic type inference, auto-complete and type checking based on your GraphQL operation.

The definition of TypedDocumentNode is super simple - it's all about the TS generics:

import { DocumentNode } from 'graphql';
export interface TypedDocumentNode<Result = {}, Variables = {}>
  extends DocumentNode {}

Can I use it now?

This library is already available to use, but it requires you to setup it in your project, since TypedDocumentNode isn't supported automatically in all GraphQL client libraries.

That's why we used patch-package to patch existing declarations, and added support to other libraries without effecting it's runtime.

You can find a list of all supported GraphQL clients here and a short getting started tutorial here.

If you are using a library that isn't supported yet, you can always add support to it manually using method overloading.

What's next?

GraphQL client libraries can easily add support for TypedDocumentNode, without breaking any API, allowing developers to have direct support for that, without the need for the supporing libraries.

And, maybe, one day, it will part of the original GraphQL DocumentNode interface ;)