Search code examples
graphqlgraphql-javagraphql-schema

Making Graphql input where input can take different types


I want to create mutation apis where input can be of different types, something like interface which we have in types. I know that we cannot have interface in input types, I want to know how we can support multiple input types in just one input. To explain the problem, I am using a dummy example:

input CreateCatInput{
  id: String
  name: String
}

input CreateDogInput{
  id: String
  name: String
  breed: String
}

input CreateElephantInput{
  id: String
  name: String
  weight: String
}

Now, if we want to write apis for it, I will have to write api for each type

createCat(input: CreateCatInput!)
createDog(input: CreateDogInput!)
createElephant(input: CreateElephantInput!)

The problem I have with this approach is:

  1. I will have to write a lot of apis, assume if I support 20 types of animal then I will have to write 20 create apis. But I don't like this many apis for the users, I want that the user should see very few apis.
  2. Assume we support 20 types of animals, how will the user know what all animals are supported, they will have to see all the apis we support in the API explorer.

The solution I am looking for is that I have only one api :

  createAnimal(input: CreateAnimalInput!)

Since interface support is not there currently, how companies are implementing input which can be of multiple types? How can I define the input such that I can only give only one input in the api ?

I have read this suggestion, but it involves defining annotations, I am currently trying it. I want to see how other people are solving this issue.

Edit: Looks like a lot of work is now done on this topic https://github.com/graphql/graphql-spec/pull/733 and the feature will be available soon.


Solution

  • Input union type can solve your problem but unfortunately it is not supported now . However , the good news is that there is already a RFC for this feature which means it is possible it will be included in the next GraphQL specification release.

    At this moment , I will model it using the nested input with an enum to differentiate which animal type the user is actually want to create. Somethings look like :

    input CreateAnimalInput{
      id:   String
      name: String
      animalType :AnimalType!
      dogParam   : CreateDogInput
      elephantParam : CreateElephantInput
    }
    
    enum AnimalType{
      DOG
      ELEPHANT
    }
    
    input CreateDogInput{
      breed: String
    }
    
    input CreateElephantInput{
      weight: String
    }
    
    createAnimal(input: CreateAnimalInput!)
    

    If an animalType is set to DOG , only values in the dogParam field will be considered and other animal parameter fields will be ignored.


    Update on Nov-2022 : Input union type is superseded by OneOf input type.