13
votes

If I have a union type like this:

union AllOnboardingQuestionTypes = StepFinal | TimeRangesQuestion | PercentQuestion | SingleSelectQuestion | MultiSelectQuestion | InformationOnly

where some of the types have the same field names but different types (e.g. answer for PercentAnswer is float whereas SingleSelect's answer is a string), is this the right way to do the query?

query OnboardingQuestionsQuery {
     onboardingQuestions {
       ... on InformationOnly {
         title
         description
         questionID
         inputType
       }
       ... on StepFinal {
          title
          description
       }
       ... on TimeRangesQuestion {
          title
          description
          timePeriods {
            timePeriod
            estimatedEnd
            estimatedStart
          }
       }
       ... on SingleSelectQuestion {
         title
         description
         questionID
         inputType
         singleSelectAnswer: answer
         singleSelectOptions: options {
           value
           label
         }
       }
       ... on MultiSelectQuestion {
         title
         description
         questionID
         inputType
         multiSelectAnswer: answer
         multiSelectOptions: options
       }
       ... on PercentQuestion {
         title
         description
         questionID
         inputType
         percentAnswer: answer
         min
         max
       }
    }
}

The aliases seem cumbersome to me and will make things tricky as I'll have to dealias when mutating data my hope was that I could just use answer instead of singleSelectAnswer.

But when I try that, I get this error:

{"errors":[{"message":"Fields \"answer\" conflict because they return conflicting types String! and [Boolean!]!. Use different aliases on the fields to fetch both if this was intentional.","locations":[{"line":64,"column":7},{"line":69,"column":7}]},{"message":"Fields \"answer\" conflict because they return conflicting types String! and Float!. Use different aliases on the fields to fetch both if this was intentional.","locations":[{"line":64,"column":7},{"line":74,"column":7}]},{"message":"Fields \"answer\" conflict because they return conflicting types [Boolean!]! and Float!. Use different aliases on the fields to fetch both if this was intentional.","locations":[{"line":69,"column":7},{"line":74,"column":7}]}]}

I'm new to GraphQL and don't know if this is the correct way to handle it. In my head I was hoping to follow a polymorphism approach but maybe that's not the way it's done.

2
not sure how helpful it will be here... but I notice the Union Types documentation lacks clarity around the requirement for any Union Type to have a __resolveType field in your Resolver: > When you have a field in your schema that returns a union or interface type, you will need to specify an extra __resolveType field in your resolver map, which tells the GraphQL executor which type the result is, out of the available options. via: ApolloGraphQL - lazaruslarue

2 Answers

0
votes

is this the right way to do the query?

Yes. Unions are restricted in this way according to the current (June2018) GraphQL specification. See also a corresponding issue on graphql.js

The aliases seem cumbersome

The best way to avoid this is for the schema to specify different field names when the return types differ.

0
votes

I had the same problem and find three different solutions to it:

  1. Using Interface
  2. Using Union
  3. Using a String with additional type information

All not very nice but working. I put a simple example project with all solutions on Github: https://github.com/chnoack/apollo-dynamic-types-example