Skip to content

fix: prevent duplicate client type declarations with graphql-codegen v7#497

Merged
nicola-smartive merged 2 commits into
mainfrom
fix/codegen-v7-duplicate-client-types
Jun 22, 2026
Merged

fix: prevent duplicate client type declarations with graphql-codegen v7#497
nicola-smartive merged 2 commits into
mainfrom
fix/codegen-v7-duplicate-client-types

Conversation

@smartive-nicolai

Copy link
Copy Markdown
Contributor

Problem

After #490 (graphql-codegen monorepo → v7), gqm generate's client output declares every type twice. In consumers (e.g. zwei-wealth-platform) the regenerated src/generated/client/index.ts gets hundreds of TS2300: Duplicate identifier (*Where/*SubWhere/Create*/Update*/enums) plus TS2567: Enum declarations can only merge with namespace or other enum declarations — breaking both type-check and the app build.

Root cause

Since @graphql-codegen/typescript-operations v6 the operations plugin visits the schema AST itself and emits every enum + input-object type an operation uses (_usedSchemaTypes) directly into its own output — unless importSchemaTypesFrom is set (typescript-operations/.../visitor.js, EnumTypeDefinition/InputObjectTypeDefinition: if (!used || importSchemaTypesFrom) return null). In v5 it emitted no schema types. generateGraphqlClientTypes() runs both typescript (full schema) and typescript-operations into a single client/index.ts, so every used input/enum is now declared twice, and ReactionType-style enums additionally clash as a real enum (typescript) vs a string-literal type alias (operations).

This is upstream dotansimha/graphql-code-generator#10782, closed not-planned; the maintainer-recommended fix is importSchemaTypesFrom.

Fix

Split the client output into two files, the idiomatic v7 way:

  • client/schema.tstypescript plugin → full schema types
  • client/index.tstypescript-operations plugin with importSchemaTypesFrom: '<gen>/client/schema' → operation types only, referencing the shared schema types

export * from './schema' is added to client/index.ts so the public import surface is unchanged — consumers still get every schema type and operation type from the single client entrypoint. The resolver side (api/index.ts) was never affected (no operations plugin) and only sees benign v7 regen (dropped unused utility types, Upload: anyunknown).

Regression test

tests/unit/generate-client-types.spec.ts asserts the generated client output has no duplicate declarations (and that historically-doubled types like CreateReview/ReactionType/ReviewWhere appear exactly once). Verified it fails on the old single-file config and passes with the fix — the exact check that would have caught #490.

Verification

  • regenerated fixtures are duplicate-free; consumer-style tsc --strict on the output → 0 errors
  • operation type names identical to the pre-v7 output (no consumer regression)
  • full suite green: npm run test (lint + 121 tests + build)

🤖 Generated with Claude Code

nicola-smartive and others added 2 commits June 22, 2026 08:29
Since graphql-codegen v7 the `typescript-operations` plugin re-emits every
enum and input-object type used by an operation into its own output, which
collided with the `typescript` plugin when both wrote to a single
`client/index.ts` — declaring every used `*Where`/`Create*`/`Update*` input
and every used enum twice (TS2300) and clashing enums as `enum` vs
string-literal `type` alias (TS2567) in consumers' generated client types.

Split the client output into `client/schema.ts` (full schema types via the
`typescript` plugin) and `client/index.ts` (operation types via
`typescript-operations`), wiring the latter to the former with
`importSchemaTypesFrom` and re-exporting via `export * from './schema'` so the
public import surface is unchanged. See dotansimha/graphql-code-generator#10782.

Add a regression test asserting the generated client output has no duplicate
declarations, and regenerate the test fixtures.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Map the `Time` scalar via its module (`@smartive/graphql-magic#Time`) and enable
`useTypeImports`, instead of injecting the import with a hard-coded `add` plugin.

The `add` import landed in the operations file (`client/index.ts`) unconditionally;
a consumer with `noUnusedLocals` whose client operations never select a `Time`
field would have hit `TS6133: 'Time' is declared but its value is never read` — a
failure mode the previous single-file layout didn't have. graphql-codegen now
emits the `Time` import only in the files that actually use it. The committed test
fixtures are unchanged (their operations do use `Time`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@nicola-smartive nicola-smartive merged commit 1753816 into main Jun 22, 2026
12 checks passed
@nicola-smartive nicola-smartive deleted the fix/codegen-v7-duplicate-client-types branch June 22, 2026 12:53
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 28.0.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant