graphql-code-generator
graphql-code-generator copied to clipboard
#9962 causes issues with our schema: parts of the types in ResolversType map contradict other parts of the type (repro)
Which packages are impacted by your issue?
@graphql-codegen/visitor-plugin-common, @graphql-codegen/typescript-resolvers
Describe the bug
With the update of @graphql-codegen/visitor-plugin-common to 5.2.0 and from that very likely this PR we run into an issue with the generated types. To me, it looks like the resolver types are improved, by replacing the base interface with its concrete implementations. This does not seem to be generated correctly in all cases.
Take the following graphql.schema (also in the Github repro repo):
type Assignment {
resource: HumanResource
}
interface Resource {
id: ID!
attributes: [Attribute!]!
}
type VehicleResource implements Resource {
id: ID!
attributes: [Attribute!]!
plateNumber: String!
}
type HumanResource implements Resource {
id: ID!
attributes: [Attribute!]!
fullName: String!
}
interface Attribute {
id: ID!
}
type JSONAttribute implements Attribute {
id: ID!
json: String!
}
type TextAttribute implements Attribute {
id: ID!
text: String!
}
type Query {
assignment: Assignment!
humanResource: HumanResource!
resource: Resource!
attribute: Attribute!
}
It contains two levels of interface to type mappings. When you look at the type generated for the Assignment resolver, the resource points to the schema base type instead of the resolver type:
export type ResolversTypes = {
// has resource: HumanResource instead of resource: ResolversTypes<'HumanResource'>
Assignment: ResolverTypeWrapper<Assignment>; // !!!
Attribute: ResolverTypeWrapper<ResolversInterfaceTypes<ResolversTypes>['Attribute']>;
Boolean: ResolverTypeWrapper<Scalars['Boolean']['output']>;
HumanResource: ResolverTypeWrapper<Omit<HumanResource, 'attributes'> & { attributes: Array<ResolversTypes['Attribute']> }>;
ID: ResolverTypeWrapper<Scalars['ID']['output']>;
JSONAttribute: ResolverTypeWrapper<JsonAttribute>;
Query: ResolverTypeWrapper<{}>;
Resource: ResolverTypeWrapper<ResolversInterfaceTypes<ResolversTypes>['Resource']>;
String: ResolverTypeWrapper<Scalars['String']['output']>;
TextAttribute: ResolverTypeWrapper<TextAttribute>;
VehicleResource: ResolverTypeWrapper<Omit<VehicleResource, 'attributes'> & { attributes: Array<ResolversTypes['Attribute']> }>;
};
What it should do, is:
export type ResolversTypes = {
// change type of resource to ResolversTypes['HumanResource']
Assignment: ResolverTypeWrapper<Omit<Assignment, 'resource'> & { resource: ResolversTypes['HumanResource'] }>;
Attribute: ResolverTypeWrapper<ResolversInterfaceTypes<ResolversTypes>['Attribute']>;
Boolean: ResolverTypeWrapper<Scalars['Boolean']['output']>;
HumanResource: ResolverTypeWrapper<Omit<HumanResource, 'attributes'> & { attributes: Array<ResolversTypes['Attribute']> }>;
ID: ResolverTypeWrapper<Scalars['ID']['output']>;
JSONAttribute: ResolverTypeWrapper<JsonAttribute>;
Query: ResolverTypeWrapper<{}>;
Resource: ResolverTypeWrapper<ResolversInterfaceTypes<ResolversTypes>['Resource']>;
String: ResolverTypeWrapper<Scalars['String']['output']>;
TextAttribute: ResolverTypeWrapper<TextAttribute>;
VehicleResource: ResolverTypeWrapper<Omit<VehicleResource, 'attributes'> & { attributes: Array<ResolversTypes['Attribute']> }>;
};
Otherwise, a mixture of types from ResolversTypes
and schema types clash with each other when trying to implement a resolver for assignment
:
Type 'Omit<HumanResource, "attribute"> & { attribute: ResolverTypeWrapper<JsonAttribute | TextAttribute>[]; }' is not assignable to type 'Maybe<HumanResource>'.
Type 'Omit<HumanResource, "attribute"> & { attribute: ResolverTypeWrapper<JsonAttribute | TextAttribute>[]; }' is not assignable to type 'HumanResource'.
Type 'Omit<HumanResource, "attribute"> & { attribute: ResolverTypeWrapper<JsonAttribute | TextAttribute>[]; }' is not assignable to type 'Resource'.
Types of property 'attribute' are incompatible.
Type 'ResolverTypeWrapper<JsonAttribute | TextAttribute>[]' is not assignable to type 'Attribute[]'.
Type 'ResolverTypeWrapper<JsonAttribute | TextAttribute>' is not assignable to type 'Attribute'.
Property 'id' is missing in type 'Promise<JsonAttribute | TextAttribute>' but required in type 'Attribute'.ts(2322)
See also this commit for how, I think, it should have been generated. To me, it looks like the logic for generation does not consider nested cases of references between interfaces that need to be resolved to their types, but I might be wrong, it's just a feeling.
Your Example Website or App
https://github.com/mx-bernhard/graphql-codegen-resolver-types
Steps to Reproduce the Bug or Issue
See repro repo. The error is visible in resolvers-types-server.ts in line 57.
I checked in the generated files. They were generated with this:
yarn install
yarn generate
Expected behavior
See this commit for how, I think, it should have been generated.
Screenshots or Videos
No response
Platform
- OS: [Windows WSL 2]
- NodeJS: [e.g. 20.13.1]
- @graphql-codegen/cli 5.0.2
- @graphql-codegen/typescript 4.0.7
- @graphql-codegen/typescript-resolvers 4.1.0
- graphql 16.8.1
Codegen Config File
No response
Additional context
The behavior cannot be observed with version 4.0.6 of @graphql-codegen-typescript-resolvers