Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

...on UnionType { fields } does not respond with the actual type of data #50

Closed
mnylen opened this issue Jul 14, 2015 · 4 comments
Closed

Comments

@mnylen
Copy link

mnylen commented Jul 14, 2015

Spec: http://facebook.github.io/graphql/#sec-Unions

I find it quite surprising that doing ...on UnionType { fields }, the response object just contains the fields and nothing about the type of the data being returned.

If we take the example in spec further and add a new type video which also has height and width fields:

type Video {
  height: Int
  width: Int
 }

And then add it to search result union type:

 Union SearchResult = Photo | Video | Person

If we had a root query search(query: "foo") that returned a GraphQLList(SearchResult) and did something like:

 {
   search(query: "foo") {
     ... on Person {
       name
     }
     ... on Video {
      width
      height
     }
     ... on Photo {
      width
      height
     }
   }
}

The response could end up looking like this:

{
 "data": {
    "search": [
      { "name": "John Doe" }, // a Person
      { "width": 1024, "height": 768 }, // a Photo
      { "width": 2560, "height": 1440 } // a Video
    ]
  }
}

How the client is supposed to know what type the results are? I could inspect the returned fields, but that doesn't work when Photo and Video has exactly the same fields. Also it feels kind of hacky.

One solution to this is add a type field for Video, Photo and Person and require the client to request that field also. But is there really a scenario where you don't need this information?

I think what should happen by default is that the value is wrapped with the actual type of each result. For example, the above response would become something like:

{
 "data": {
    "search": [
      { "Person": { "name": "John Doe" } }, // a Person
      { "Photo": { "width": 1024, "height": 768 } }, // a Photo
      { "Video": { "width": 2560, "height": 1440 } } // a Video
    ]
  }
}

With this response, the client can just loop over the results and do something like this:

if (result.Person) { renderPersonResult(result.Person) }
else if (result.Photo) { renderPhotoResult(result.Photo) }
else if (result.Video) { renderVideoResult(result.Video) }

What do you think?

@mnylen
Copy link
Author

mnylen commented Jul 14, 2015

Okay, __typename solves this. Might be good idea to have this in the union example though, because I guess a lot of people are going to need this.

So the query becomes:

 {
   search(query: "foo") {
     __typename

     ... on Person {
       name
     }
     ... on Video {
      width
      height
     }
     ... on Photo {
      width
      height
     }
   }
}

@mnylen mnylen closed this as completed Jul 14, 2015
@mnylen mnylen reopened this Jul 14, 2015
@leebyron
Copy link
Contributor

Keeping this open as a note to include this in the full documentation we're working on.

@leebyron
Copy link
Contributor

__typename exists for exactly this purpose :)

@leebyron
Copy link
Contributor

leebyron commented Apr 7, 2016

Closing out this issue since it's aging, but continual documentation improvements will help with this kind of confusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants