ton1
ton1

Reputation: 7628

Dynamic type in GraphQL

const typeDef = `

  type User {
    id: ID!
    name: String!
    email: String!
  }
  type Post { 
    id: ID!
    title: String!
    content: String!
  }
  extend type Query {
    getDocuments(collection: String!): [User] || [Post]     // <<<<< Here!
  }   
`

Is it possible to define getDocuments type to [User] or [Post] both? I have several data collections (users, posts, payments etc...) and I want to define one getter getDocuments for fetching data for reducing duplicated code.

// like this

getDocuments(collection: 'User')
getDocuments(collection: 'Post')

Upvotes: 0

Views: 788

Answers (1)

Daniel Rearden
Daniel Rearden

Reputation: 84687

From the spec:

GraphQL supports two abstract types: interfaces and unions.

An Interface defines a list of fields; Object types that implement that interface are guaranteed to implement those fields. Whenever the type system claims it will return an interface, it will return a valid implementing type.

A Union defines a list of possible types; similar to interfaces, whenever the type system claims a union will be returned, one of the possible types will be returned.

So you can do something like this:

union Document = User | Post

extend type Query {
  getDocuments(collection: String!): [Document]
}

If the types share one or more fields, you can use an Interface -- otherwise, you have to use a Union.

The field's type will be resolved at runtime based on the resolveType function you provide. See here for additional details on how to provide the function to your type.

Lastly, when querying your field, you'll now need to use fragments to specify which fields to request depending on the type:

getDocuments {
  ... on User {
    id
    name
  }
  ... on Post {
    id
    title
  }
}

Upvotes: 1

Related Questions