Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you make a graphql type both an input and output type?

I have some object types that I'd like to use as both input and output - for instance a currency type or a reservation type.

How do I define my schema to have a type that supports both input and output - I don't want to duplicate code if I don't have to. I'd also prefer not to create duplicate input types of things like currency and status enums.

export const ReservationInputType = new InputObjectType({   name: 'Reservation',   fields: {     hotelId: { type: IntType },     rooms: { type: new List(RoomType) },     totalCost: { type: new NonNull(CurrencyType) },     status: { type: new NonNull(ReservationStatusType) },   }, });  export const ReservationType = new ObjectType({   name: 'Reservation',   fields: {     hotelId: { type: IntType },     rooms: { type: new List(RoomType) },     totalCost: { type: new NonNull(CurrencyType) },     status: { type: new NonNull(ReservationStatusType) },   }, }); 
like image 649
MonkeyBonkey Avatar asked Jan 06 '17 22:01

MonkeyBonkey


People also ask

Is it possible to use inheritance with GraphQL input types?

No, the spec does not allow input types to implement interfaces. And GraphQL type system in general does not define any form of inheritance (the extends keyword adds fields to an existing type, and isn't for inheritance).

What is difference between type and input in GraphQL?

Types in GraphQL are grouped into output types and input types. Output types are types that may be returned as part of a response produced by a GraphQL service. Input types are types that are valid inputs for field or directive arguments.

What are the three types of operations in GraphQL?

There are three types of operations that GraphQL models: query – a read‐only fetch. mutation – a write followed by a fetch. subscription – a long‐lived request that fetches data in response to source events.

How do you input type in GraphQL?

To make your schema simpler, you can use “input types” for this, by using the input keyword instead of the type keyword. id: ID! Here, the mutations return a Message type, so that the client can get more information about the newly-modified Message in the same request as the request that mutates it.


2 Answers

In the GraphQL spec, objects and input objects are distinct things. Quoting the spec for input objects:

Fields can define arguments that the client passes up with the query, to configure their behavior. These inputs can be Strings or Enums, but they sometimes need to be more complex than this.

The Object type... is inappropriate for re‐use here, because Objects can contain fields that express circular references or references to interfaces and unions, neither of which is appropriate for use as an input argument. For this reason, input objects have a separate type in the system.

An Input Object defines a set of input fields; the input fields are either scalars, enums, or other input objects. This allows arguments to accept arbitrarily complex structs.

While an implementation might provide convenience code to create an object and a corresponding input object from a single definition, under the covers, the spec indicates that they'll have to be separate things (with separate names, such as Reservation and ReservationInput).

like image 183
CommonsWare Avatar answered Sep 19 '22 22:09

CommonsWare


While working on a project I had a similar problem with code duplication between input and type objects. I did not find the extend keyword very helpful as it only extended the fields of that specific type. So the fields in type objects cannot not be inherited in input objects.

In the end I found this pattern using literal expressions helpful:

const UserType = `     name: String!,     surname: String! `;  const schema = graphql.buildSchema(`     type User {         ${UserType}     }     input InputUser {         ${UserType}     } `)  
like image 35
spedy Avatar answered Sep 19 '22 22:09

spedy