Good Idea
Good Idea

Reputation: 2821

Using GraphQL Fragment on multiple types

If I have a set of field that is common to multiple types in my GraphQL schema, is there a way to do something like this?

type Address {
  line1: String
  city: String
  state: String 
  zip: String
}

fragment NameAndAddress on Person, Business {
  name: String
  address: Address
}

type Business {
   ...NameAndAddress
   hours: String
}

type Customer {
   ...NameAndAddress
   customerSince: Date
}

Upvotes: 43

Views: 29307

Answers (3)

Flavien Volken
Flavien Volken

Reputation: 21309

You can, but GraphQL won't let you make a fragment between 2 types unless you specify into the schema that those types are sharing the same properties. To do so, you have to use an interface. You will then be able to build a fragment of this interface on the client side.

Server side schema:


interface NameAndAddress {
  name: String
  address: Address
}


type Address {
  line1: String
  city: String
  state: String 
  zip: String
}

type Business implements NameAndAddress {
  # by design you have to write those properties again
  name: String
  address: Address

  hours: String
}

type Customer implements NameAndAddress {
  name: String
  address: Address

  customerSince: Date
}

Then on your client

# define a fragment on the interface
fragment NameAndAddress on NameAndAddress {
  name: String
  address: Address
}

# you can then get the fields as follow
query {
  business {
     ...NameAndAddress
  }

  customer {
     ...NameAndAddress
  }
}

Upvotes: 8

aleclofabbro
aleclofabbro

Reputation: 1699

Don't know if it was not available at this question time, but I guess interfaces should fit your needs

Upvotes: 3

Daniel Rearden
Daniel Rearden

Reputation: 84687

Fragments are only used on the client-side when making requests -- they can't be used inside your schema. GraphQL does not support type inheritance or any other mechanism that would reduce the redundancy of having to write out the same fields for different types.

If you're using apollo-server, the type definitions that make up your schema are just a string, so you can implement the functionality you're looking for through template literals:

const nameAndAddress = `
  name: String
  address: Address
`

const typeDefs = `
  type Business {
     ${nameAndAddress}
     hours: String
  }

  type Customer {
     ${nameAndAddress}
     customerSince: Date
  }
`

Alternatively, there are libraries out there, like graphql-s2s, that allow you to use type inheritance.

Upvotes: 21

Related Questions