`typescript-operations` emits an unused schema-types import when fragment types are referenced

Author: wassim-mirusCreated Aug 19, 2026Updated Sep 17, 2026

Which packages are impacted by your issue?

@graphql-codegen/typescript-operations

Describe the bug

With importSchemaTypesFrom and inlineFragmentTypes: 'combine', a document that only spreads a fragment gets an import type * as Types it never references. Under noUnusedLocals that fails the build.

Reproduction

bash
npm install
npm run generate
npm run typecheck
src/book.generated.ts(4,1): error TS6133: 'Types' is declared but its value is never read.

Two fragments, in separate files. Only Category selects the enum field:

graphql
# src/category.graphql
fragment Category on Category { id kind }   # kind: CategoryKind!

# src/book.graphql
fragment Book on Book { id category { ...Category } }

src/category.generated.ts — import used, correct:

typescript
import type * as Types from '../types';

export type CategoryFragment = { id: string, kind: Types.CategoryKind };

src/book.generated.ts — import emitted, never referenced:

typescript
import { CategoryFragment } from './category.generated';
import type * as Types from '../types';   // <-- unused

export type BookFragment = { id: string, category: CategoryFragment };

Expected

No Types import in src/book.generated.ts, since nothing in the file refers to it.

Cause

TypeScriptDocumentsVisitor.getExternalSchemaTypeImports() (packages/plugins/typescript/operations/src/visitor.ts) gates the import on _usedSchemaTypes:

typescript
const hasTypesToImport =
  Object.values(this._usedSchemaTypes).filter(
    value => value.type === 'GraphQLEnumType' || value.type === 'GraphQLInputObjectType',
  ).length > 0;

if (!hasTypesToImport) {
  return [];
}

CategoryKind is used by the document, so this is true for both files. But used by the document and named by the generated file are different, and only the second justifies an import. _usedSchemaTypes cannot answer the second on its own: it also decides whether enum and input definitions are generated locally, which must account for types reached through fragments.

Only inlineFragmentTypes decides which of the two applies:

inlineFragmentTypes BookFragment names Types? tsc
'inline' (default) { category: { id: string, kind: Types.CategoryKind } } yes passes
'combine' { category: CategoryFragment } no fails

Your Example Website or App

https://stackblitz.com/edit/gdtmg1pc

Steps to Reproduce the Bug or Issue

Run npm generate in the repro

Expected behavior

It should not have unused imports

Screenshots or Videos

No response

Platform

package version
@graphql-codegen/cli 7.2.0
@graphql-codegen/typescript-operations 6.1.6
@graphql-codegen/near-operation-file-preset 5.2.2
graphql 16.11.0
typescript 5.9.3

Codegen Config File

typescript
import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: './schema.graphql',
  documents: './src/**/*.graphql',
  config: {
    // Fragment types are referenced, not inlined. This is what makes the bug observable:
    // a document that only spreads a fragment never names the schema-types namespace itself.
    inlineFragmentTypes: 'combine',
  },
  generates: {
    // Shared Input/Enum types, per the v6 migration guide's multi-file setup.
    './types.ts': {
      plugins: ['typescript-operations'],
      config: {
        generateOperationTypes: false,
      },
    },
    // Per-document operation types, importing the shared types from the file above.
    './src': {
      preset: 'near-operation-file',
      presetConfig: {
        extension: '.generated.ts',
      },
      plugins: ['typescript-operations'],
      config: {
        importSchemaTypesFrom: './types.ts',
        namespacedImportName: 'Types',
      },
    },
  },
};

export default config;

Source: dotansimha/graphql-code-generator