Interfaces with many implementations generate massive output even when only one type is queried via fragment
- Dominant language
- Go
- Stars
- 1.3k
- Forks
- 143
- Avg merge
- 4h 50m
- Merged PRs (30d)
- 1
Description
**Is your feature request related to a problem? Please describe.**
When a query selects from an interface type that has many implementations in the schema (e.g. `Node` in the GitHub API with 300+ types), genqlient generates a struct and `implementsGraphQLInterface` marker method for every single implementation — even if the query only uses fragments for one or two of them.
For example, this query:
```graphql
query GetThread($threadID: ID!) {
node(id: $threadID) {
... on PullRequestReviewThread {
comments(first: 100) {
nodes { body }
}
}
}
}
```
generates thousands of lines like:
```go
func (v *GetThreadNodeOrganization) implementsGraphQLInterfaceGetThreadNode() {}
func (v *GetThreadNodeOrganizationInvitation) implementsGraphQLInterfaceGetThreadNode() {}
func (v *GetThreadNodePackage) implementsGraphQLInterfaceGetThreadNode() {}
func (v *GetThreadNodePackageFile) implementsGraphQLInterfaceGetThreadNode() {}
// ... hundreds more
```
Each unreferenced type gets an identical struct (only shared fields) plus getter methods, marshal/unmarshal cases, and interface marker methods. The only type that actually has unique fields is `PullRequestReviewThread`.
**Describe the solution you'd like**
Only generate full implementation structs for types explicitly referenced by inline fragments or named fragment spreads.
Unreferenced types could share a single catch-all "other" struct with just the
shared fields.
**Describe alternatives you've considered**
- `# @genqlient(struct: true)` works when there are no fragments, but errors when we have fragments.
- `# @genqlient(bind: "MyCustomType")` works too, but I'm using genqlient because I can't be trusted to manually maintain types.
**Additional context**
I have an llm-generated branch that addresses this. If you are interested in pursuing this issue I can use that as a starting point for implementation.
Contributor guide
Research direction
Reproduce the shown GetThread query and trace the generator path that expands GraphQL interface implementations. Compare the generated output for referenced and unreferenced types; done means unreferenced implementations no longer receive full structs and methods while referenced inline fragments and named fragment spreads remain usable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, graphql
- Domain
- api, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100