graphql-code-generator: Fragments do not combine arrays correctly
Describe the bug
Including multiple fragments that contain the same arrays results in the types getting combined at the array level. TS doesn’t know how to merge these correctly. That is Array<TypeA> & Array<TypeB> is not equivalent to Array<TypeA & TypeB> because TS doesn’t merge arrays.
To Reproduce Steps to reproduce the behavior: This repro has the bug fully reproducible.
https://github.com/chrbala/apollo-bug-repro/tree/codegen-merge-arrays
- My GraphQL schema:
type Item {
string: String!
number: Int!
}
type Query {
items: [Item!]!
}
- My GraphQL operations:
query Page {
...String
...Number
}
fragment String on Query {
items {
string
}
}
fragment Number on Query {
items {
number
}
}
- My
codegen.ymlconfig file:
overwrite: true
schema: "src/schema.js"
documents: "src/**/*.tsx"
generates:
src/generated/graphql.tsx:
plugins:
- "typescript"
- "typescript-operations"
- "typescript-react-apollo"
Expected behavior
You should be able to access both the string and number properties on items, but you can only access string. If you switch the order of ...String and ...Number, then you can only access number.
The generated fragment is
export type PageQuery = (
{ __typename?: 'Query' }
& NumberFragment
& StringFragment
);
But for it to work correctly in TS, it would need to be more like
export type PageQuery = (
{ __typename?: 'Query' }
& {
items: Array<NumberFragment['items'][0] & StringFragment['items'][0]>
}
);
Environment:
- OS: OSX 10.14.6
- Codegen “@graphql-codegen/cli”: “1.21.5”, “@graphql-codegen/introspection”: “1.18.2”, “@graphql-codegen/typescript”: “1.22.1”, “@graphql-codegen/typescript-operations”: “1.18.0”, “@graphql-codegen/typescript-react-apollo”: “2.2.5”,
- NodeJS: v12.13.1
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 20 (3 by maintainers)
Hey @chrbala, I created https://github.com/dotansimha/graphql-code-generator/pull/6184 which changes the default behavior to generate more friendly types for all use-cases.
You can install the changes of the PR locally via
(as new commits are pushed the list of packages is updated over here
Please let me know whether this addresses your issues!
@dotansimha This is a bit tricky, as we generate types per fragment, but maybe there is some kind of merge TypeScript utility that can take two deep types and merge them?
It seems like this would be possible via recursive conditional types: https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-rc/#recursive-conditional-types
@chrbala If you could create a PR with a failing test case, that would be highly appreciated! Edit: I just realized that it does not make sense to create failing test case without knowing the solution to the problem 😅
I can have a in-depth look at it this week!
Hi @dotansimha and @n1ru4l , I’m also running into errors related to this in
@graphql-codegen/typescriptversions2.1.2. It seems that if you request an array of interfaces field multiple times, spreading fragments on them leads to invalid state. This could commonly happen when a set of subcomponents define fragments on the same type and each request different fields on an interface array. I have a reproducible repo here: https://codesandbox.io/s/gql-test-forked-j275t?file=/src/index.tsx (schema is found insrc/schema.js, query is found insrc/index.tsx)You can pop a terminal and run
yarn codegento see the error.relevant packages
here’s the schema and query:
Schema
Repro Query
My real use case looks something closer to the below
gqloperations, but after playing around I determined that it also happens if you request the interface array multiple times even with the same fragment type (seen above aschildren { ... on ItemA { itemAOnlyField } })Real Query
The error I get when trying to compile:
Thanks for your help on this!
Yes, this example is more close to the example provided by @chrbala : https://www.typescriptlang.org/play?ssl=10&ssc=3&pln=1&pc=1#code/C4TwDgpgBAglC8sBOSCGIA8BvKBnYSAlgHYDmAXHgSaVAL4B8A3AFCiRQBCCyamOxAK4BbAEYQklIWIn1mLNuGgBZCaQgwUGADIQAZsADKhACYQANFABKhUgAsjpiAx66Dxs1AgAPYBGImuLzoGCR6sm7AACpKLgD81rYOHtA+fgFBmnyhxOFIifbRsVAJWSGRMRwAZAUOlc5QUhAAbrJNrUisihyqSOomPL3qWRgwlpzyLADGAPbE+FB++JRDEAOIANosUFA4+ERklABER5bS4pJQAIz0LAC6TEA