简体   繁体   中英

GraphQL - Using same field names in different types within union

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 (eg 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.

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.

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

There is a GraphQL limitation which does not allow to spread the same fields multiple times inside the GraphQL tag. The best way to avoid this is for the schema to specify different field names when the return types differ, indeed. A quick FE fix for this would be renaming the duplicate fetched fields (fields with the same name which are part of different types) from gql tag:

query OnboardingQuestionsQuery {
 onboardingQuestions {
   ... on InformationOnly {
     infoOnlyTitle: title
     infoOnlyDescription: description
     questionID
     inputType
   }
   ... on StepFinal {
      stepFinalTitle: title
      stepFinalDescription: description
   }
   ... on TimeRangesQuestion {
      timeRangesQuestionTitle: title
      timeRangesQuestionDescription: description
      timePeriods {
        timePeriod
        estimatedEnd
        estimatedStart
      }
   }
   ... on SingleSelectQuestion {
     singleSelectQuestionTitle: title
     singleSelectQuestionDescription: description
     questionID
     inputType
     singleSelectAnswer: answer
     singleSelectOptions: options {
       value
       label
     }
   }
   ... on MultiSelectQuestion {
     multiSelectQuestionTitle: title
     multiSelectQuestionDescription: description
     questionID
     inputType
     multiSelectAnswer: answer
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM