Skip to content

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

@WillAbides

Description

@WillAbides

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:

query GetThread($threadID: ID!) {
    node(id: $threadID) {
        ... on PullRequestReviewThread {
            comments(first: 100) {
                nodes { body }
            }
        }
    }
}

generates thousands of lines like:

    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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions