- 
                Notifications
    You must be signed in to change notification settings 
- Fork 2.1k
docs: type generation for graphql servers #4376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
          
     Merged
      
        
      
    
  
     Merged
                    Changes from 5 commits
      Commits
    
    
            Show all changes
          
          
            14 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      b3b489f
              
                add guide for graphQL server type generation
              
              
                sarahxsanders e157546
              
                feedback
              
              
                sarahxsanders d0cdf3a
              
                fix spellcheck
              
              
                sarahxsanders 9450057
              
                Merge branch '16.x.x' into type-generation
              
              
                sarahxsanders a2175c3
              
                feedback from Eddy
              
              
                sarahxsanders 8983716
              
                Update website/pages/docs/type-generation.mdx
              
              
                sarahxsanders b7eb06c
              
                Update website/pages/docs/type-generation.mdx
              
              
                sarahxsanders 0f50ddb
              
                Update website/pages/docs/type-generation.mdx
              
              
                sarahxsanders 866ff83
              
                Update website/pages/docs/type-generation.mdx
              
              
                sarahxsanders b691052
              
                spellcheck
              
              
                sarahxsanders c11f237
              
                add install steps
              
              
                sarahxsanders 93ac2b2
              
                Merge branch '16.x.x' into type-generation
              
              
                sarahxsanders f15186f
              
                Apply suggestions from code review
              
              
                benjie 643a862
              
                Merge branch '16.x.x' into type-generation
              
              
                benjie File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -25,6 +25,7 @@ overrides: | |
| - swcrc | ||
| - noreferrer | ||
| - xlink | ||
| - codegen | ||
| - composability | ||
| - deduplication | ||
|  | ||
|  | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,248 @@ | ||
| --- | ||
| title: Type Generation for GraphQL | ||
| sidebarTitle: Type Generation | ||
| --- | ||
|  | ||
| # Type Generation for GraphQL | ||
|  | ||
| Writing a GraphQL server in JavaScript or TypeScript often involves managing complex | ||
| types. As your API grows, keeping these types accurate and aligned with your schema | ||
| becomes increasingly difficult. | ||
|  | ||
| Type generation tools automate this process. Instead of manually defining or maintaining | ||
| TypeScript types for your schema and operations, these tools can generate them for you. | ||
| This improves safety, reduces bugs, and makes development easier to scale. | ||
|  | ||
| This guide walks through common type generation workflows for projects using | ||
| `graphql-js`, including when and how to use them effectively. | ||
|  | ||
| ## Why use type generation? | ||
|  | ||
| Type generation improves reliability and developer experience across the development | ||
| lifecycle. It's especially valuable when: | ||
|  | ||
| - You want strong type safety across your server logic | ||
| - Your schema is defined separately in SDL files | ||
| - Your API surface is large, rapidly evolving, or used by multiple teams | ||
| - You rely on TypeScript for editor tooling, autocomplete, or static analysis | ||
|  | ||
| By generating types directly from your schema, you can avoid drift between schema | ||
| definitions and implementation logic. | ||
|  | ||
| ## Code-first development | ||
|  | ||
| In a code-first workflow, the schema is constructed entirely in JavaScript or TypeScript | ||
| using `graphql-js` constructors like `GraphQLObjectType`, `GraphQLSchema`, and others. | ||
| This approach is flexible and lets you build your schema programmatically using native | ||
| language features. | ||
|  | ||
| If you're using this approach with TypeScript, you already get some built-in type safety | ||
| with the types exposed by `graphql-js`. For example, TypeScript can help ensure your resolver | ||
| functions return values that match their expected shapes. | ||
|  | ||
| However, code-first development has tradeoffs: | ||
|  | ||
| - You won't get automatic type definitions for your resolvers unless you generate | ||
| them manually or infer them through wrappers. | ||
| - Schema documentation, testing, and tool compatibility may require you to export | ||
| the schema to SDL first. | ||
|  | ||
| You can still use type generation tools like GraphQL Code Generator in a code-first setup. | ||
| You just need to convert your schema into SDL. | ||
|  | ||
| To export your schema: | ||
|         
                  benjie marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
|  | ||
| ```ts | ||
| import { printSchema } from 'graphql'; | ||
| import { schema } from './schema'; | ||
| import { writeFileSync } from 'fs'; | ||
|  | ||
| writeFileSync('./schema.graphql', printSchema(schema)); | ||
| ``` | ||
|  | ||
| Once you've written the SDL, you can treat the project like a schema-first project | ||
| for type generation. | ||
|         
                  benjie marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
|  | ||
| ## Schema-first development | ||
|  | ||
| In a schema-first workflow, your GraphQL schema is written in SDL, for example, `.graphql` | ||
| or `.gql` files. This serves as the source of truth for your server. This approach | ||
|         
                  benjie marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| emphasizes clarity because your schema is defined independently from your business logic. | ||
|  | ||
| Schema-first development pairs well with type generation because the schema is | ||
| serializable and can be directly used by tools like [GraphQL Code Generator](https://the-guild.dev/graphql/codegen). | ||
|  | ||
| With a schema-first workflow, you can: | ||
|  | ||
| - Generate resolver type definitions and files that match your schema | ||
| - Generate operation types for client queries, integration tests, or internal tooling | ||
| - Detect breaking changes and unused types through schema diffing tools | ||
|  | ||
| ## Generating resolver types | ||
|  | ||
| We recommend using the [Server Preset](https://www.npmjs.com/package/@eddeee888/gcg-typescript-resolver-files) for a | ||
| managed workflow. It automatically generates types and files based on your schema without needing extra plugin setup. | ||
|  | ||
| The Server Preset generates: | ||
|  | ||
| - Resolver types, including parent types, arguments, return values, and context | ||
| - Resolver files with types wired up, ready for your business logic | ||
| - A resolver map and type definitions to plug into GraphQL servers | ||
|  | ||
| This setup expects your schema is split into modules to improve readability and maintainability. For example: | ||
|  | ||
| ```pgsql | ||
| ├── src/ | ||
| │ ├── schema/ | ||
| │ │ ├── base/ | ||
| │ │ │ ├── schema.graphql | ||
| │ │ ├── user/ | ||
| │ │ │ ├── schema.graphql | ||
| │ │ ├── book/ | ||
| │ │ │ ├── schema.graphql | ||
| ``` | ||
|  | ||
| Here's an example `codegen.ts` file using the Server Preset: | ||
|  | ||
| ```ts filename="codegen.ts" | ||
| import type { CodegenConfig } from "@graphql-codegen/cli"; | ||
| import { defineConfig } from "@eddeee888/gcg-typescript-resolver-files"; | ||
|  | ||
| const config: CodegenConfig = { | ||
| schema: "src/**/schema.graphql", | ||
| generates: { | ||
| "src/schema": defineConfig({ | ||
| resolverGeneration: "minimal", | ||
| }), | ||
| }, | ||
| }; | ||
|  | ||
| export default config; | ||
| ``` | ||
|  | ||
| To generate the resolver types and files, run: | ||
|  | ||
| ```bash | ||
| npx graphql-codegen | ||
| ``` | ||
|  | ||
| This creates resolver files like: | ||
|  | ||
| ```ts | ||
|         
                  sarahxsanders marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| import type { QueryResolvers } from "./../../../types.generated"; | ||
|  | ||
| export const user: NonNullable<QueryResolvers["user"]> = async ( | ||
| _parent, | ||
| _arg, | ||
| _ctx, | ||
| ) => { | ||
| // Implement Query.user resolver logic here | ||
| }; | ||
| ``` | ||
|  | ||
| The user query resolver is typed to ensure that the user resolver expects an id argument and returns a | ||
| User, giving you confidence and autocomplete while implementing your server logic, which may look like this: | ||
|  | ||
| ```ts | ||
|         
                  sarahxsanders marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| export const user: NonNullable<QueryResolvers["user"]> = async ( | ||
| parent, | ||
| args, | ||
| context, | ||
| ) => { | ||
| return context.db.getUser(args.id); | ||
| }; | ||
| ``` | ||
|  | ||
| See the official [Server Preset guide](https://the-guild.dev/graphql/codegen/docs/guides/graphql-server-apollo-yoga-with-server-preset) to learn about its other features, including mappers convention and static analysis for runtime safety. | ||
|  | ||
| ## Generating operation types | ||
|  | ||
| In addition to resolver types, you can generate types for GraphQL operations such as queries, mutations, and | ||
| fragments. This is especially useful for shared integration tests or client logic that needs to match the schema | ||
| precisely. | ||
|  | ||
| We recommend using the GraphQL Code Generator [Client Preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client) for a managed workflow: | ||
|  | ||
| - Write operations with GraphQL syntax in the same file where it is used | ||
| - Get type-safety when using the result | ||
|  | ||
| Here's an example configuration using the Client Preset: | ||
|  | ||
| ```ts | ||
|         
                  sarahxsanders marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| import type { CodegenConfig } from "@graphql-codegen/cli"; | ||
|  | ||
| const config: CodegenConfig = { | ||
| schema: "src/**/schema.graphql", | ||
| documents: ["src/**/*.ts"], | ||
| ignoreNoDocuments: true, | ||
| generates: { | ||
| "./src/graphql/": { | ||
| preset: "client", | ||
| config: { | ||
| documentMode: "string", | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
|  | ||
| export default config; | ||
| ``` | ||
|  | ||
| To keep generated types up to date as you edit your code, run the generator in watch mode: | ||
|  | ||
| ```bash | ||
| npx graphql-codegen --config codegen.ts --watch | ||
| ``` | ||
|  | ||
| Once generated, import the `graphql` function from `src/graphql/` to write GraphQL operations | ||
| directly in your TypeScript files: | ||
|  | ||
| ```ts | ||
|         
                  sarahxsanders marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| import { graphql } from "./graphql"; | ||
|  | ||
| const UserQuery = graphql(` | ||
| query User($id: ID!) { | ||
| user(id: ID!) { | ||
| id | ||
| fullName | ||
| } | ||
| } | ||
| `); | ||
|  | ||
| const response = await fetch("https://graphql.org/graphql/", { | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/json", | ||
| Accept: "application/graphql-response+json", | ||
| }, | ||
| body: JSON.stringify({ | ||
| query: UserQuery, | ||
| variables: { id: "1" }, | ||
| }), | ||
| }); | ||
|  | ||
| if (!response.ok) { | ||
| throw new Error("Network response was not ok"); | ||
| } | ||
|  | ||
| const result: ResultOf<typeof UserQuery> = await response.json(); | ||
|  | ||
| console.log(result); | ||
| ``` | ||
|  | ||
| For guides on using the Client Preset with popular frameworks and tools, see: | ||
|  | ||
| - [Vanilla TypeScript](https://the-guild.dev/graphql/codegen/docs/guides/vanilla-typescript) | ||
| - [React Query](https://the-guild.dev/graphql/codegen/docs/guides/react-query) | ||
| - [React / Vue](https://the-guild.dev/graphql/codegen/docs/guides/react-vue) | ||
|  | ||
| ## Best practices for CI and maintenance | ||
|  | ||
| To keep your type generation reliable and consistent: | ||
|  | ||
| - Check in generated files to version control so teammates and CI systems don't produce | ||
| divergent results. | ||
| - Run type generation in CI to ensure types stay in sync with schema changes. | ||
| - Use schema diffing tools like `graphql-inspector` to catch breaking changes before | ||
| they're merged. | ||
| - Automate regeneration with pre-commit hooks, GitHub Actions, or lint-staged workflows. | ||
      
      Oops, something went wrong.
        
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.