graphql-code-generator icon indicating copy to clipboard operation
graphql-code-generator copied to clipboard

Duplicate fields can be generated when using fragments and aliases

Open Georgegriff opened this issue 4 months ago • 0 comments

Which packages are impacted by your issue?

@graphql-codegen/visitor-plugin-common

Describe the bug

I've noticed it's possible to generate invalid typescript where two keys have the same name. I've got a repro, its a little contrived the example but it's synthesised from some real (albeit dodgy) production code fiddling with ID keys.

Image

See how id is duplicated instead of being merged down to one field in GetItems_items_Item_owner_User

I've added PR with a fixed test: https://github.com/dotansimha/graphql-code-generator/pull/10531

Your Example Website or App

https://github.com/dotansimha/graphql-code-generator/pull/10531

Steps to Reproduce the Bug or Issue

Using the following schema:

type Query {
  items: [Item!]!
}

type Item {
  id: ID!
  name: String!
  owner: User
}

type User {
  id: ID!
  realId: ID!
  name: String!
}

And this kinda wierd query

query GetItems {
  items {
    id
    name
    ...FragmentA
    ...FragmentB
  }
}

fragment FragmentA on Item {
  owner {
    id: realId
    name
  }
}

fragment FragmentB on Item {
  owner {
    id
    name
  }
}

and this codegen config extractAllFieldsToTypes being the important bit

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

const config: CodegenConfig = {
  schema: "app/models/Notifications/repro-bug-2/schema.graphql",
  documents: ["app/models/Notifications/repro-bug-2/queries/**/*.graphql"],
  config: {
    preResolveTypes: true,
    namingConvention: "keep",
    avoidOptionals: {
      field: true,
    },
    nonOptionalTypename: true,
    skipTypeNameForRoot: true,
    extractAllFieldsToTypes: true,
    skipDocumentsValidation: {
      skipValidationAgainstSchema: true,
      ignoreRules: true,
      skipDuplicateValidation: true,
    },
    omitOperationSuffix: true,
  },
  generates: {
    "./global-types.ts": {
      plugins: ["typescript"],
    },
    "./generated/": {
      preset: "near-operation-file",
      presetConfig: {
        baseTypesPath: "./global-types.ts",
        folder: "types",
      },
      plugins: ["typescript-operations"],
    },
  },
};

export default config;

You end up with the duplicated key

Expected behavior

id key not duped

Screenshots or Videos

No response

Platform

  • OS: [e.g. macOS, Windows, Linux]
  • NodeJS: [e.g. 18.5.0]
  • graphql version: [e.g. 16.3.0]
  • @graphql-codegen/* version(s): [e.g. 2.6.2]

Codegen Config File

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

const config: CodegenConfig = { schema: "app/models/Notifications/repro-bug-2/schema.graphql", documents: ["app/models/Notifications/repro-bug-2/queries/**/*.graphql"], config: { preResolveTypes: true, namingConvention: "keep", avoidOptionals: { field: true, }, nonOptionalTypename: true, skipTypeNameForRoot: true, extractAllFieldsToTypes: true, skipDocumentsValidation: { skipValidationAgainstSchema: true, ignoreRules: true, skipDuplicateValidation: true, }, omitOperationSuffix: true, }, generates: { "./global-types.ts": { plugins: ["typescript"], }, "./generated/": { preset: "near-operation-file", presetConfig: { baseTypesPath: "./global-types.ts", folder: "types", }, plugins: ["typescript-operations"], }, }, };

export default config;

Additional context

No response

Georgegriff avatar Dec 05 '25 14:12 Georgegriff