dotansimha / graphql-code-generator

A tool for generating code based on a GraphQL schema and GraphQL operations (query/mutation/subscription), with flexible support for custom plugins.
https://the-guild.dev/graphql/codegen/
MIT License
10.8k stars 1.32k forks source link

typescript-operations: Missing types with a nested fragment when exportFragmentSpreadSubTypes and skipTypename are enabled #4890

Open OscarBarrett opened 3 years ago

OscarBarrett commented 3 years ago

Describe the bug When both exportFragmentSpreadSubTypes and skipTypename are true, some types are not generated when a fragment has certain nested objects.

To Reproduce Reproduction here: https://codesandbox.io/s/great-noyce-wdyut Missing types are shown in the no-undef lint errrors.

  1. My GraphQL schema:
interface BlockInterface {
  uid: String
  title: String
}

type Root_BlockType implements BlockInterface {
  uid: String
  title: String
  children: [BlockInterface]
}
type Child_BlockType implements BlockInterface {
  uid: String
  title: String
  children: [BlockInterface]
}

type FragmentOne_Type implements BlockInterface {
  uid: String
  title: String
}
type FragmentTwo_Type implements BlockInterface {
  uid: String
  title: String
}
type FragmentThree_Type implements BlockInterface {
  uid: String
  title: String
}

union Blocks = Root_BlockType | Child_BlockType

type Result implements BlockInterface {
  uid: String
  title: String
  blocks: Blocks
}

type Query {
  search: BlockInterface
}
  1. My GraphQL operations:
fragment RootBlockFields on Root_BlockType {
  __typename
  uid
}

fragment RootChildren on BlockInterface {
  ...FragmentOne
  ...FragmentTwo
}

fragment RootBlock on Root_BlockType {
  ...RootBlockFields

  children {
    ...RootChildren
    ...ChildBlock
  }
}

fragment ChildChildren on BlockInterface {
  ...FragmentOne
  ...FragmentTwo
  ...FragmentThree
}

fragment ChildBlock on Child_BlockType {
  __typename
  uid

  children {
    ...ChildChildren

    ...on Root_BlockType {
      ...RootChildren

      children {
        ...on Child_BlockType {
          __typename
          uid

          children {
            ...ChildChildren
          }
        }
      }
    }
  }
}

fragment FragmentOne on FragmentOne_Type {
  __typename
  uid
}

fragment FragmentTwo on FragmentTwo_Type {
  __typename
  uid
  title
}

fragment FragmentThree on FragmentThree_Type {
  __typename
  uid
  title
}

query SampleQuery {
  search {
    ...on Result {
      __typename

      blocks {
        ...RootBlock
      }
    }
  }
}
  1. My codegen.yml config file:
schema: schema.graphql
documents: document.graphql
generates:
  types.ts:
    plugins:
      - typescript
      - typescript-operations
config:
  exportFragmentSpreadSubTypes: true
  skipTypename: true

Expected behavior All types should be generated. Instead, the generated operation types reference the following types that are not defined:

Environment:

Additional context

OscarBarrett commented 3 years ago

I've been looking into this a bit more. If __typename is explicitly added to all named and inline fragments in the operations, the missing types are generated.

e.g. for the example provided

--- a/document.graphql
+++ b/document.graphql
@@ -4,11 +4,13 @@ fragment RootBlockFields on Root_BlockType {
 }

 fragment RootChildren on BlockInterface {
+  __typename
   ...FragmentOne
   ...FragmentTwo
 }

 fragment RootBlock on Root_BlockType {
+  __typename
   ...RootBlockFields

   children {
@@ -18,6 +20,7 @@ fragment RootBlock on Root_BlockType {
 }

 fragment ChildChildren on BlockInterface {
+  __typename
   ...FragmentOne
   ...FragmentTwo
   ...FragmentThree
@@ -31,6 +34,7 @@ fragment ChildBlock on Child_BlockType {
     ...ChildChildren

     ...on Root_BlockType {
+      __typename
       ...RootChildren

       children {

Perhaps these should be generated as empty types if __typename is not included?

Kcazer commented 3 years ago

I opened a similar issue (#3950) some time ago

At the time, we wrote a custom script to manually fix the generated types (this script was later replaced with an afterAllFileWrite hook). Currently, our current schema doesn't have this issue anymore since the interface causing it was removed.

jamiter commented 2 years ago

@OscarBarrett, did you have any progress on this issue?