This repository is the home for graphql-typed-document-node
and integration related to it.
You can read more, see example and try it out live here
graphql-typed-document-node
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 a fully type result object and variables object.
It made possible by TypeScript type inference.
This project works in the following way:
- Configure your project to use this library (see
How to use?
). - You write your GraphQL operations (
query
/mutation
/subscription
/fragment
) in any way your prefer (for example - in a.graphql
file). - GraphQL Code Generator will generate a
TypedDocumentNode
for your operations (which is a bundle of pre-compiledDocumentNode
with the operation result type and variables type). - Instead of using your
.graphql
file - import the generatedTypedDocumentNode
and use it with your GraphQL client framework. - You'll get automatic type inference, auto-complete and type checking based on your GraphQL operation.
Most libraries supports DocumentNode
as the type of the query object, but that's not enough to use this library.
Our goal is to get built-in support in major libraries, in order
In order to extend the behavior, we are using patch-package
library internally, to add support for TypedDocumentNode
and add the support for type inference.
The following patches are currently supported:
@apollo/client
(since3.2.0
, if you are using React Components (<Query>
) you still need a patch)apollo-angular
(since2.6.0
)@urql/core
(since1.15.0
)@urql/preact
(since1.4.0
)urql
(since1.11.0
)@urql/exchange-graphcache
(since3.1.11
)@urql/svelte
(since1.1.3
)villus
(since1.0.0-beta.8
)graphql-js
(since15.2.0
)@vue/apollo-composable
(since4.0.0-alpha.13
)graphql-request
(since5.0.0
)
graphql-js
(v16)
graphql
(14.7.0
,15.0.0
,15.1.0
,~15.2.0
)@apollo/client
(~3.0.0
,~3.1.0
)apollo-client
(~2.6.10
, includingapollo-cache
)react-apollo
(3.1.5
)apollo-angular
(1.10.1
)
You can find a set of examples here
To use this library, following these instructions:
- Install this library, and GraphQL Codegen and the relevant plugins:
yarn add -D @graphql-typed-document-node/core @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typed-document-node
And if you don't already have a dependency for graphql
, add it to your project:
yarn add graphql
Codegen is needed because we need to precompile
.graphql
files intoDocumentNode
, and burns the types in it to createTypedDocumentNode
object.
- Create GraphQL-Codegen configuration file, and point to your GraphQL schema and your
.graphql
operations files:
schema: SCHEMA_FILE_OR_ENDPOINT_HERE
documents: "./src/**/*.graphql"
generates:
./src/graphql-operations.ts:
plugins:
- typescript
- typescript-operations
- typed-document-node
- Try to run codegen by using:
yarn graphql-codegen
, it should create the./src/graphql-operations.ts
file for you, with the generatedTypedDocumentNode
objects.
If you are using a library that doesn't support TypedDocumentNode
yet, you can apply a patch, by doing:
- Install the patch-cli:
yarn add -D @graphql-typed-document-node/patch-cli
- Configure the patch CLI to run as
postinstall
script:
{
"scripts": {
"postinstall": "patch-typed-document-node"
}
}
- Reinstall dependencies (using npm or yarn) - it will now patch the relevant libraries.
Now, after installing your projects' dependencies, it will make sure to patch all relevant packages and make it available for use with TypedDocumentNode
.
The core
package of typed-document-node exports 3 types only:
TypedDocumentNode
- the base of this library.ResultOf
- a utils for extracting the result type from an existingTypeDocumentNode
instance (ResultOf<typeof MyQueryDocument>
)VariablesOf
- a utils for extracting the variables type from an existingTypeDocumentNode
instance (VariablesOf<typeof MyQueryDocument>
)
If you are a library maintainer, and you wish to have built-in TS support in your library, you can add support for TypedDocumentNode
without having any breaking changes to your API.
Basically, in any place where you need to have typed access to the result type of an operation, or to a typed variables object, make sure to have generics for both types, and use TypeDocumentNode
in your arguments, instead of DocumentNode
. This will allow TypeScript to infer the types based on the object you are passing to it later.
type GqlFetchResult = {
data?: any;
errors?: Error[];
}
export function gqlFetch(operation: DocumentNode, variables?: Record<string, any>): GqlFetchResult {
// ...
}
import { TypedDocumentNode } from "@graphql-typed-document-node/core";
type GqlFetchResult<TData = any> = {
data?: TData;
errors?: Error[];
}
export function gqlFetch<TData = any, TVariables = Record<string, any>>(operation: TypedDocumentNode<TData, TVariables>, variables?: TVariables): GqlFetchResult<TData>;
export function gqlFetch<TData = any, TVariables = Record<string, any>>(operation: DocumentNode, variables?: TVariables): GqlFetchResult<TData> {
// ...
}
You can create patches using patch-package
and change the .d.ts
files of any package to add support for TypedDocumentNode
.
If you think your patch can be helpful for other developers as well, feel free to open a PR in this repo and add it!
- dotansimha/graphql-code-generator#1777 (comment) for the concept of generating unified clients support
- https://github.com/Shopify/quilt/blob/main/packages/graphql-typed/src/index.ts for similar idea