Khan / genqlient

a truly type-safe Go GraphQL client
MIT License
1.07k stars 107 forks source link

Use Schema types for Response #244

Closed ameddin73 closed 1 year ago

ameddin73 commented 1 year ago

Is your feature request related to a problem? Please describe. I am working with many different fragments on the same type which all become different types in go and make using them in the same functions almost impossible! Particularly, if a pair of fragments have the same field made of different fragments, it's impossible to make a shared interface because of type hell.

Describe the solution you'd like Why not just return the whole dang type? You already have the whole schema, why not just generate structs for each graphql type and use that as the return type for any query on it?

Describe alternatives you've considered I don't know that much so I imagine this may have been considered and decided against. I'd love to hear the reasoning if so. If not, please add this feature! It's silly to have a type just because I wanted to make a smaller query!

ameddin73 commented 1 year ago

Just learned about directives and for now I think these will solve my problem, but I do feel like the question stands.

benjaminjkraft commented 1 year ago

Thanks for raising this question! We have a few ways of dealing with shared types in genqlient -- you can read more about them in the documentation.

To answer one of your specific questions, we intentionally don't return all fields of a type, because your query didn't query all fields of that type, so they will be unset! That is, while your User type may have dozens of fields, if your query only asks for two of them, only those two will be returned, and so genqlient's struct will only contain those fields so you don't accidentally expect the others to be set.

ameddin73 commented 1 year ago

Thanks for the response! I wonder if there's a technical barrier to returning the complete type (even if most of it is empty)?

I feel that in many situations the flexibility of a shared type between many queries may outweigh the negatives of a mostly unfilled struct.

For example, I can imagine a situation where a print function would take a single type, but be called by a list and a get function. The list may have a smaller fragment in its query, but because it returns the same type, we can reuse the print function.

What are your thoughts?

benjaminjkraft commented 1 year ago

Just to be clear, it's an intentional choice not to return the complete type; there's no technical barrier but rather it's designed that way to ensure that it's clear to readers what fields of the type will actually be set. I'd encourage you to read through the documentation I linked above; it should be entirely possible to have a reusable print function via a fragment that includes the fields needed by the print function which both the get and list queries include.