Graphql-code-generator: Invalid TypeScript definitions generated

Created on 7 Oct 2019  Â·  12Comments  Â·  Source: dotansimha/graphql-code-generator

Describe the bug

Invalid TypeScript definitions are generated.

export type GetMovieQuery = { node:  };
                                   ^

To Reproduce
Steps to reproduce the behavior:

  1. My GraphQL schema:
type Query {
  node(gid: ID!): Node
}

interface Node {
  gid: ID!
}

interface Entity {
  gid: ID!
  active: Boolean!
} 

type Movie implements Node, Entity {
  gid: ID!
  active: Boolean!
  name: String!
}
  1. My GraphQL operations:
query getMovie($gid: ID!) {
  node(gid: $gid) {
    ... on Entity {
      gid
    }
  }
}
  1. My codegen.yml config file:
schema: var/schema.json
overwrite: true
generates:
  assets/graphql/types.tsx:
    documents: 'assets/**/*.gql'
    plugins:
      - typescript
      - typescript-operations
    config:
      nonOptionalTypename: false
      skipTypename: true
      preResolveTypes: true

Expected behavior

types.tsx should be a valid TS file.

Environment:

  • OS: macOS 10.14.6
  • @graphql-codegen/add: 1.8.1
  • @graphql-codegen/cli: 1.8.1
  • @graphql-codegen/fragment-matcher: 1.8.1
  • @graphql-codegen/typescript: 1.8.1
  • @graphql-codegen/typescript-operations: 1.8.1
  • NodeJS: 12.10.0
bug plugins waiting-for-release

All 12 comments

Please note that changing the query to this:

query getMovie($gid: ID!) {
  node(gid: $gid) {
    gid
    ... on Entity {
      ...SomeEntityFragment
    }
  }
}

Results in this:

export type GetMovieQuery = {
  node:
    | { gid: string }
    | { gid: string }
    | { gid: string }
    | { gid: string }
    | { gid: string }
    | { gid: string }
    | { gid: string }
    | { gid: string }
    | { gid: string }
};

Where { gid: string } is produced for each type implementing Node.
Moreover, the fields from SomeEntityFragment are not generated.

When using version 1.7.0 the following type is generated:

export type GetMovieQuery = { node: {  } | {  } | {  } | {  } | {  } | {  } | {  } | {  } | {  } | {  } | {  } };

I tracked down the bug and it looks like the issue is the 2 interface levels. If I add a new entrypoint:

type Query {
  entity(gid: String!): Entity!
}

And change the query to:

fragment EntityBrandActivation on Entity {
  gid
  brandData(brand: $brand) {
    active
  }
}

fragment EntityCacheKey on Entity {
  ... on Company {
    id
  }
  ... on Movie {
    id
  }
  ... on Series {
    id
  }
  ... on Person {
    id
  }
  ... on Theater {
    id
  }
}

query getEntityBrandActivation($gid: ID!, $brand: ID!) {
  entity(gid: $gid) {
    ...EntityBrandActivation
    ...EntityCacheKey
  }
}

Then the generated types are:

export type GetEntityBrandActivationQueryVariables = {
  gid: Scalars['ID'],
  brand: Scalars['ID']
};

export type GetEntityBrandActivationQuery = { entity: ({  } | {  } | {  } | {  } | {  } | {  } | {  } | {  } | {  } | {  } | {  })
//                                                     ^^^^
//                                            this is weird
    & EntityBrandActivationFragment
    & EntityCacheKeyFragment
   };

I tried 1.8.2-alpha-a83224e6.9 and a new bug appeared:

export type GetEntityBrandActivationQuery = { entity: (
    EntityBrandActivation_User_Fragment
    & EntityCacheKey_User_Fragment
  ) | (
    EntityBrandActivation_Company_Fragment
    & EntityCacheKey_Company_Fragment
  ) | (
    EntityBrandActivation_Image_Fragment
    & EntityCacheKey_Image_Fragment
  ) | (
    EntityBrandActivation_Series_Fragment
    & EntityCacheKey_Series_Fragment
  ) | (
    EntityBrandActivation_Person_Fragment
    & EntityCacheKey_Person_Fragment
  ) | (
    EntityBrandActivation_Episode_Fragment
    & EntityCacheKey_Episode_Fragment
  ) …

Instead of generating empty objects it now generates fragments. However, some fragment types are not generated which results in an error:

Cannot find name 'EntityCacheKey_Screen_Fragment' .ts(2304)

@ooflorent Any chance you can share a complete schema and queries that reproduces those issues?

Unfortunately I'm not allowed to share this. I'm sorry… Due to the lack of information, I'd understand if you'd want to close the issue. I tried to reproduce the issue by pruning our schema but wasn't able to accurately reproduce the issue.

@ooflorent I really want to solve it :)
Is it possible to share it with type A {} type B {}? only with the minimal types that reproduces the error, I think it's happens because some kind of combination of interfaces and unions.

@ooflorent Can you just share how your types are defined? (for example - type A implements B, interface B, union C = D | A or something similar)

Here is an extract of our schema:

interface Node {
  id: ID!
}

scalar DateTime

interface Element {
  active: Boolean!
  createdAt: DateTime!
  createdBy: User
  updatedAt: DateTime!
  updatedBy: User
}

interface Entity {
  brandData(brand: ID!): EntityBrandData
}

type EntityBrandData {
  active: Boolean!
  description: String!
  title: String!
}

type Query {
  node(id: ID!): Node!
}

type Company implements Element & Node & Entity {
  active: Boolean!
  createdAt: DateTime!
  createdBy: User
  updatedAt: DateTime!
  updatedBy: User
  id: ID!
  brandData(brand: ID!): EntityBrandData
  # …
}

type Theater implements Element & Node & Entity {
  active: Boolean!
  createdAt: DateTime!
  createdBy: User
  updatedAt: DateTime!
  updatedBy: User
  id: ID!
  brandData(brand: ID!): EntityBrandData
  # …
}

type Movie implements Element & Node & Entity {
  active: Boolean!
  createdAt: DateTime!
  createdBy: User
  updatedAt: DateTime!
  updatedBy: User
  id: ID!
  brandData(brand: ID!): EntityBrandData
  # …
}

type User implements Element & Node & Entity {
  active: Boolean!
  createdAt: DateTime!
  createdBy: User
  updatedAt: DateTime!
  updatedBy: User
  id: ID!
  brandData(brand: ID!): EntityBrandData
  # …
}

And the query:

query getEntityBrandData($gid: ID!, $brand: ID!) {
  node(gid: $gid) {
    __typename
    id
    ... on Entity {
      ...EntityBrandData
    }
    ... on Element {
      ...ElementMetadata
    }
    ... on Company {
      # …
    }
    ... on Theater {
      # …
    }
  }
}

fragment EntityBrandData on Entity {
  brandData(brand: $brand) {
    active
    browsable
    title
    alternateTitle
    description
  }
}

fragment ElementMetadata on Element {
  createdAt
  createdBy {
    id
    name
  }
  updatedAt
  updatedBy {
    id
    name
  }
}

As you can see, we use a lot the interfaces…

Managed to reproduce it here

@ooflorent I think I managed to fix this issue in: https://github.com/dotansimha/graphql-code-generator/pull/2737

Can you please try the latest alpha? 1.8.2-alpha-9ae02b14.29

Fixed in 1.8.2.

Was this page helpful?
0 / 5 - 0 ratings