You could define them as a union (or interface if all implementing types share common fields)
Union schema example:
type Query {
blocks: [ ContentBlock! ]!
}
type Video {
url: String!
}
type Quote {
body: String!
author: String
}
type Advertisement {
src: String!
backgroundColor: String
}
union ContentBlock = Video | Quote | Advertisement
Interface schema example:
type Query {
blocks: [ ContentBlock! ]!
}
type Video implements ContentBlock {
id: ID!
url: String!
}
type Quote implements ContentBlock {
id: ID!
body: String!
author: String
}
type Advertisement implements ContentBlock {
id: ID!
src: String!
backgroundColor: String
}
interface ContentBlock {
id: ID!
}
Example resolver:
{
ContentBlock: {
__resolveType (source) {
if (source.url) return 'Video'
if (source.src) return 'Advertisment'
if (source.author || source.body) return 'Quote'
}
}
}
Example query:
{
blocks {
...on Video {
url
}
...on Quote {
body
author
}
...on Advertisement {
src
backgroundColor
}
}
}
More reading on Unions and Interfaces in GraphQL