Khan / Khan/genqlient

Interfaces with many implementations generate massive output even when only one type is queried via fragment

Open
#416 2 comments 0 reactions 0 assignees View on GitHub
enhancement
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.