Migrating from Apollo-tooling to GraphQL Code Generator
Migrating from Apollo-tooling (apollo client:codegen) to GraphQL Code Generator. What has changed? How to migrate? What configuration options replace apollo-tooling's behaviour?
Apollo-tooling (the apollo CLI, specifically
apollo client:codegen) is a code generation tool that generates TypeScript types from GraphQL
operations for use with Apollo Client.
This guide explains how to replace it with GraphQL Code Generator, which is actively maintained, more flexible, and supports a broader range of use cases.
This guide is using the programmatic CLI version of GraphQL Codegen.
Installation
Remove apollo-tooling and install GraphQL Code Generator:
Required packages
| Package | Description |
|---|---|
@graphql-codegen/cli | Core CLI that runs the code generator |
@graphql-codegen/typescript-operations | Plugin that generates TypeScript types for GraphQL operations |
@graphql-codegen/near-operation-file-preset | Preset that places generated files next to their source operations |
Configuration
Apollo-tooling is configured via apollo.config.js (or apollo.config.ts) and invoked with
apollo client:codegen. GraphQL Code Generator uses a codegen.ts file and is invoked with
graphql-codegen cli command or programmatically.
Per-operation file generation with near-operation-file
Apollo-tooling’s default behaviour is to generate one TypeScript file per graphql operation, placed
in a __generated__ folder next to the source. For example, given src/Component.ts containing a
query GetUser, apollo-tooling produces src/__generated__/GetUser.ts.
GraphQL Code Generator replicates this with the filePerOperation: true parameter of the
near-operation-file preset.
With this configuration: src/Component.ts → src/__generated__/GetUser.ts, matching Apollo
Tooling’s output structure exactly.
If you need to generate files per-source file (default to GraphQL Codegen), remove the following
config option: filePerOperation: true (or set it to false). Then, the output will be:
src/Component.ts → src/__generated__/Component.ts
Nested field types naming conventions
Nested fields are the fields inside operation result object.
Apollo-tooling generates nested field type names using only field names, omitting the GraphQL object type name:
By default GraphQL Codegen always adds field types:
To achieve naming similar to apollo-tooling with GraphQL Codegen use the
extractAllFieldsToTypesCompact: true configuration option:
Enum types
Apollo-tooling generates enums as native TypeScript enum declarations and references them directly
by name (without any namespace prefix):
GraphQL Code Generator generates string literal union types by default. To produce native enum
declarations matching apollo-tooling’s output, set enumType: 'native':
Recommended configuration
Below is a configuration that produces output closely matching apollo-tooling’s behaviour, including per-file generation, enum output, and type naming:
Manual changes
The setup above closely mimics apollo-tooling (99.98% similarity in our tests) but isn’t an exact match. The following items may require manual fixes:
1. Nested field types naming.
In very rare cases, the field names generated by GraphQL Codegen don’t match apollo-tooling’s. Update these cases manually.
2. Enum file location.
Occasionally, GraphQL Codegen places enums in a different file then apollo-tooling. If an enum is missing, check nearby generated files and adjust your imports accordingly.
3. is possibly null and has any type typecheck bugs.
These bugs has to be fixed.
For is possibly null bug, asserting for not null or adding ! will fix most cases:
For has any type bug - a proper type needs to be determined.
4. Mismatch between Type | null and Type | null | undefined.
Experiment with the following configuration options to keep your codebase changes to a minimum:
- maybeValue: defaults to
T | null, set toT | null | undefinedif necessary - inputMaybeValue: defaults to
Maybe<T>, set toT | null | undefinedif necessary - avoidOptionals: Replaces ? optional modifier with explicit
Maybe<T>. Supports granular control via object form. - allowUndefinedQueryVariables: Adds | undefined to Query operation variable types (not Mutation/Subscription)
- optionalResolveType: Makes
__resolveTypeoptional (__resolveType?) in resolver types. - nullability: When
errorHandlingClient: true, adjusts nullability for fields marked with@semanticNonNulldirective (requiresgraphql-sock).
5. Extra __typename present, or required __typename is missing.
Experiment with the following configuration options to keep your codebase changes to a minimum:
- skipTypename: prevents adding
__typenameto generated types unless explicitly in the selection set. - skipTypeNameForRoot: skips
__typenamespecifically for root types (Query, Mutation, Subscription). Ignored if__typenameis explicitly in the selection set - nonOptionalTypename: always adds
__typenameand makes it a required (non-optional) field. - addTypenameToSelectionSets: injects
__typenamedirectly into the generated document node selection sets. - resolversNonOptionalTypename: makes
__typenamenon-optional in resolver mappings without affecting base types. Supports granular control via object form.