Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusing input type as fragment in GraphQL [duplicate]

Tags:

types

graphql

A very common use case in GraphQL is creating an object with a mutation, and receiving the exact same fields back, plus and ID returned by the database. Here's a related question asking about this.

My question is, how can this pattern be simplified to avoid repeated fields? I've tried reusing the input type as a fragment,

input ClientInput {
  short_name: String
  full_name: String
  address: String
  email: String
  location: String  
}

type Client {
  id: String
  ...ClientInput
}

...but that failed with

Syntax Error: Expected Name, found ...

All the documentation and blog posts I've seen on Fragments always creates them on an existing type. That means still repeating all but the ID field:

type Client {
  _id: String
  short_name: String
  full_name: String
  address: String
  email: String
  location: String
}

fragment ClientFields on Client {
  short_name: String
  full_name: String
  address: String
  email: String
  location: String
}

input ClientInput {
  ...ClientFields
}

How is that any better?

like image 979
Dan Dascalescu Avatar asked Sep 22 '18 02:09

Dan Dascalescu


1 Answers

TL;DR: A mechanism for allowing fields to be shared between an object type and an input object type just does not exist. Fragments can only be used client-side when composing queries.

From the specification:

Fragments allow for the reuse of common repeated selections of fields, reducing duplicated text in the document.

The intent behind fragments is that you may have any number of saved queries that query the same type -- you don't want to have to update 20 different queries if the schema changes or you decide you don't need a certain field anymore.

A similar mechanism for allowing fields to be shared between a Type and an Input Type server-side just does not exist. This is likely largely by design because even though a Type field and an Input Type field both have some kind of type, they may have other properties. For example, Input Type fields can have a default value, while that property does not exist for a Type field. Similarly, Type fields have resolvers and arguments, which Input Type fields do not.

If you really want to keep things DRY, there may be workarounds available, depending on what kind of GraphQL server you're running. If it's a GraphQL.js server that uses a schema created from one or more SDL strings, for example, you can just use template literals:

const sharedClientFields = `
    short_name: String
    full_name: String
    address: String
    email: String
    location: String 
`
const schema = `
  type Client {
    _id: String
    ${sharedClientFields}
  }

  type ClientInput {
    ${sharedClientFields}
  }
`
like image 81
Daniel Rearden Avatar answered Sep 21 '22 02:09

Daniel Rearden