Graphql-js: Unable to query fields of union type even if all types in union are object types

Created on 5 Jul 2015  Â·  4Comments  Â·  Source: graphql/graphql-js

const Good = new GraphQLObjectType({
  name: 'Good',
  fields: {
    title: {type: GraphQLString}
  }
})

const Product = new GraphQLUnionType({
  name: 'Product',
  types: [Good],
  resolveType(root) {
    return Good
  }
})
{ errors:
   [ { message: 'Cannot query field title on Product',
       locations: [ { line: 14, column: 13 } ] } ] }

Most helpful comment

This is intentional, when querying against a Union you must narrow the type by using a fragment.

{
  product {
    ... on Good {
      title
    }
  }
}

This ensures that your query will be resilient to the evolution of the type schema over time. When this client has shipped, and you introduce a new type into your Product union, your client can safely ignore those additional typed items. If you were to query a field without first specifying the concrete Object type, then a new type could be added which happens to have a title field and now your existing client is overfetching and potentially rendering incorrectly.

If title is a critical part of what a Product is, such that you want to guarantee that you can always query title regardless of what concrete Object type is in use, then you should use an Interface instead of a Union.

All 4 comments

Found the solution — GraphQLInterfaceType should be used to union object types.

This is intentional, when querying against a Union you must narrow the type by using a fragment.

{
  product {
    ... on Good {
      title
    }
  }
}

This ensures that your query will be resilient to the evolution of the type schema over time. When this client has shipped, and you introduce a new type into your Product union, your client can safely ignore those additional typed items. If you were to query a field without first specifying the concrete Object type, then a new type could be added which happens to have a title field and now your existing client is overfetching and potentially rendering incorrectly.

If title is a critical part of what a Product is, such that you want to guarantee that you can always query title regardless of what concrete Object type is in use, then you should use an Interface instead of a Union.

Can you please write an example? I get cannot query field {name} error no matter what I do when I call on common fields. Should I always call with fragments?

{
  product {
    title // common fields (all types)
    ... on Good {
      // other fields
    }
  }
}

@vslinko Thanks to this I know what you mean now.

Was this page helpful?
0 / 5 - 0 ratings