Exploring OneOf in GraphQL Programming

Avatar

By squashlabs, Last Updated: March 20, 2024

Exploring OneOf in GraphQL Programming

Union Type in GraphQL

In GraphQL, a union type is used to represent a type that can be one of several possible types. It allows a field to return different types of objects based on a condition. Union types are declared using the union keyword in the schema definition language (SDL).

Here’s an example of how to define a union type in GraphQL:

union SearchResult = Book | Movie

type Book {
  title: String
  author: String
}

type Movie {
  title: String
  director: String
}

type Query {
  search(query: String): [SearchResult]
}

In the above example, the SearchResult union type can represent either a Book or a Movie object. The search query returns an array of SearchResult objects, which can be of either type.

Here’s how you can query for a union type in GraphQL:

query {
  search(query: "GraphQL") {
    ... on Book {
      title
      author
    }
    ... on Movie {
      title
      director
    }
  }
}

In the above query, we use the ... on syntax to specify the fields we want to retrieve for each possible type of the SearchResult union. Depending on the actual type of the returned object, the corresponding fields will be populated.

Related Article: Exploring GraphQL Playground Query Variables

Interface Type in GraphQL

In GraphQL, an interface type is used to define a common set of fields that can be implemented by multiple object types. It allows for polymorphism in the schema, where a field can return different types of objects that share a common interface. Interface types are declared using the interface keyword in SDL.

Here’s an example of how to define an interface type in GraphQL:

interface Animal {
  name: String
  age: Int
  makeSound: String
}

type Dog implements Animal {
  name: String
  age: Int
  makeSound: String
  breed: String
}

type Cat implements Animal {
  name: String
  age: Int
  makeSound: String
  color: String
}

type Query {
  getAnimal(name: String): Animal
}

In the above example, the Animal interface defines a common set of fields that all implementing types (Dog and Cat) must have. The getAnimal query returns an Animal object, which can be of either type.

Here’s how you can query for an interface type in GraphQL:

query {
  getAnimal(name: "Fluffy") {
    name
    age
    makeSound
    ... on Dog {
      breed
    }
    ... on Cat {
      color
    }
  }
}

In the above query, we use the ... on syntax to specify the fields we want to retrieve for each possible type of the Animal interface. Depending on the actual type of the returned object, the corresponding fields will be populated.

Schema Stitching in GraphQL

Schema stitching is a technique in GraphQL that allows you to combine multiple schemas into a single, unified schema. It enables you to create a schema that represents the entire API surface area of your application, even if the underlying data sources have separate schemas.

There are different approaches to schema stitching, but one common way is to use the mergeSchemas function from the graphql-tools library. This function takes an array of schemas and merges them together to create a new schema.

Here’s an example of how to use mergeSchemas to stitch two schemas together:

const { mergeSchemas } = require('graphql-tools');
const { makeExecutableSchema } = require('graphql-tools');

// Schema 1
const typeDefs1 = `
  type Query {
    hello: String
  }
`;

const resolvers1 = {
  Query: {
    hello: () => 'Hello from Schema 1',
  },
};

const schema1 = makeExecutableSchema({ typeDefs: typeDefs1, resolvers: resolvers1 });

// Schema 2
const typeDefs2 = `
  type Query {
    goodbye: String
  }
`;

const resolvers2 = {
  Query: {
    goodbye: () => 'Goodbye from Schema 2',
  },
};

const schema2 = makeExecutableSchema({ typeDefs: typeDefs2, resolvers: resolvers2 });

// Stitched Schema
const stitchedSchema = mergeSchemas({ schemas: [schema1, schema2] });

In the above example, we define two separate schemas (schema1 and schema2) with their respective types and resolvers. Then, we use mergeSchemas to combine them into a single stitchedSchema.

Now, you can execute queries against the stitched schema and it will resolve fields from both underlying schemas:

query {
  hello
  goodbye
}

The above query will return:

{
  "data": {
    "hello": "Hello from Schema 1",
    "goodbye": "Goodbye from Schema 2"
  }
}

Schema stitching allows you to modularize your GraphQL schemas and combine them as needed, making it easier to manage and extend your API surface area.

Enum Type in GraphQL

In GraphQL, an enum type is used to define a list of possible values for a field. It restricts the possible values that can be assigned to a field to a specific set of options. Enum types are declared using the enum keyword in SDL.

Here’s an example of how to define an enum type in GraphQL:

enum DayOfWeek {
  MONDAY
  TUESDAY
  WEDNESDAY
  THURSDAY
  FRIDAY
  SATURDAY
  SUNDAY
}

type Event {
  name: String
  day: DayOfWeek
}

type Query {
  getEvents: [Event]
}

In the above example, the DayOfWeek enum type defines a set of possible values representing the days of the week. The Event type has a day field of type DayOfWeek, which can only be assigned one of the defined enum values.

Here’s how you can query for an enum type in GraphQL:

query {
  getEvents {
    name
    day
  }
}

The above query will return a list of events with their names and the corresponding day of the week.

Enums provide a way to enforce a specific set of options for a field, making the schema more explicit and self-documenting.

Related Article: Step by Step Process: Passing Enum in GraphQL Query

Input Type in GraphQL

In GraphQL, an input type is used to represent the input arguments of a field or the input types of mutations. They are similar to object types, but they cannot have fields that return object types. Input types are declared using the input keyword in SDL.

Here’s an example of how to define an input type in GraphQL:

input UserInput {
  name: String
  age: Int
  email: String
}

type User {
  id: ID
  name: String
  age: Int
  email: String
}

type Mutation {
  createUser(input: UserInput): User
}

In the above example, the UserInput input type represents the input arguments for the createUser mutation. It has fields for the name, age, and email of the user. The createUser mutation takes a UserInput as an argument and returns a User object.

Here’s how you can use an input type in a mutation:

mutation {
  createUser(input: { name: "John Doe", age: 30, email: "john.doe@example.com" }) {
    id
    name
    age
    email
  }
}

The above mutation creates a new user with the specified input and returns the created user object.

Input types allow you to pass complex data structures as arguments to fields or mutations, making it easier to define and handle input data in your GraphQL schema.

Schema Composition in GraphQL

Schema composition in GraphQL refers to the process of combining multiple GraphQL schemas together to create a single, unified schema. It allows you to modularize your schema definition and reuse existing schemas across different parts of your application.

There are different approaches to schema composition, but one common way is to use the mergeSchemas function from the graphql-tools library. This function takes an array of schemas and merges them together to create a new schema.

Here’s an example of how to use mergeSchemas to compose two schemas together:

const { mergeSchemas } = require('graphql-tools');
const { makeExecutableSchema } = require('graphql-tools');

// Schema 1
const typeDefs1 = `
  type Query {
    hello: String
  }
`;

const resolvers1 = {
  Query: {
    hello: () => 'Hello from Schema 1',
  },
};

const schema1 = makeExecutableSchema({ typeDefs: typeDefs1, resolvers: resolvers1 });

// Schema 2
const typeDefs2 = `
  type Query {
    goodbye: String
  }
`;

const resolvers2 = {
  Query: {
    goodbye: () => 'Goodbye from Schema 2',
  },
};

const schema2 = makeExecutableSchema({ typeDefs: typeDefs2, resolvers: resolvers2 });

// Composed Schema
const composedSchema = mergeSchemas({ schemas: [schema1, schema2] });

In the above example, we define two separate schemas (schema1 and schema2) with their respective types and resolvers. Then, we use mergeSchemas to combine them into a single composedSchema.

Now, you can execute queries against the composed schema and it will resolve fields from both underlying schemas:

query {
  hello
  goodbye
}

The above query will return:

{
  "data": {
    "hello": "Hello from Schema 1",
    "goodbye": "Goodbye from Schema 2"
  }
}

Schema composition allows you to build a unified GraphQL schema from modular components, making it easier to manage and extend your API surface area.

Query Type in GraphQL

In GraphQL, the query type is a special type that defines the entry point for all read operations. It represents the root of the query execution tree and provides the structure for retrieving data from the GraphQL server.

Here’s an example of how to define a query type in GraphQL:

type Query {
  hello: String
  user(id: ID!): User
  users: [User]
}

type User {
  id: ID
  name: String
  age: Int
  email: String
}

In the above example, the Query type defines three fields: hello, user, and users. The hello field returns a string, while the user field takes an ID argument and returns a User object. The users field returns an array of User objects.

Here’s how you can query for a field on the query type in GraphQL:

query {
  hello
  user(id: "123") {
    id
    name
    age
    email
  }
  users {
    id
    name
    age
    email
  }
}

The above query will return the value of the hello field, the user with the specified id, and the list of all users.

The query type serves as the starting point for retrieving data in a GraphQL schema and defines the available fields and their return types.

Related Article: Achieving Production-Ready GraphQL

Mutation Type in GraphQL

In GraphQL, the mutation type is a special type that defines the entry point for all write operations. It represents the root of the mutation execution tree and provides the structure for modifying data on the GraphQL server.

Here’s an example of how to define a mutation type in GraphQL:

type Mutation {
  createUser(input: CreateUserInput!): User
  updateUser(id: ID!, input: UpdateUserInput!): User
  deleteUser(id: ID!): Boolean
}

input CreateUserInput {
  name: String!
  age: Int!
  email: String!
}

input UpdateUserInput {
  name: String
  age: Int
  email: String
}

type User {
  id: ID
  name: String
  age: Int
  email: String
}

In the above example, the Mutation type defines three fields: createUser, updateUser, and deleteUser. The createUser field takes a CreateUserInput as an argument and returns a User object. The updateUser field takes an ID and an UpdateUserInput as arguments and returns a User object. The deleteUser field takes an ID as an argument and returns a boolean.

Here’s how you can execute a mutation in GraphQL:

mutation {
  createUser(input: { name: "John Doe", age: 30, email: "john.doe@example.com" }) {
    id
    name
    age
    email
  }
  updateUser(id: "123", input: { name: "Jane Doe" }) {
    id
    name
    age
    email
  }
  deleteUser(id: "123")
}

The above mutation creates a new user, updates an existing user’s name, and deletes a user with the specified id.

The mutation type allows you to define operations that modify data on the GraphQL server, providing a way to create, update, and delete resources.

Subscription Type in GraphQL

In GraphQL, the subscription type is a special type that defines the entry point for real-time updates. It represents the root of the subscription execution tree and provides the structure for subscribing to data changes on the GraphQL server.

Here’s an example of how to define a subscription type in GraphQL:

type Subscription {
  newMessage: Message
}

type Message {
  id: ID
  content: String
  createdAt: DateTime
}

In the above example, the Subscription type defines a single field newMessage that returns a Message object. Subscribers can listen to the newMessage field to receive real-time updates whenever a new message is created.

Here’s how you can subscribe to a field on the subscription type in GraphQL:

subscription {
  newMessage {
    id
    content
    createdAt
  }
}

The above subscription will establish a real-time connection with the GraphQL server and receive updates whenever a new message is created.

The subscription type allows you to define real-time capabilities in your GraphQL schema, enabling clients to receive real-time updates from the server.

Introspection in GraphQL

Introspection in GraphQL refers to the ability to query the schema itself to retrieve information about the available types, fields, and directives. It allows clients to dynamically discover the capabilities of a GraphQL server and interact with it in a more flexible way.

GraphQL provides a built-in __schema field that can be used to perform introspection queries. This field returns a representation of the schema as a JSON object.

Here’s an example of how to perform an introspection query in GraphQL:

query {
  __schema {
    types {
      name
      kind
      description
      fields {
        name
        type {
          name
          kind
        }
      }
    }
  }
}

The above query retrieves information about all the types in the schema, including their names, kinds, descriptions, and fields.

Related Article: Implementing TypeORM with GraphQL and NestJS

Additional Resources

Defining a Union Type in GraphQL
Advantages of Using Interfaces in GraphQL

You May Also Like

Tutorial: GraphQL Input Interface

GraphQL input interface is a crucial tool in programming that enables data manipulation and retrieval. This article takes an in-depth look at its role and usage,... read more

Managing Data Queries with GraphQL Count

Managing data queries in programming can be a challenging task, but with GraphQL Count, you can simplify the process. This article explores the syntax for counting... read more

Exploring Directus GraphQL

Implementing Directus GraphQL in your programming routine can greatly enhance your development process. This article offers a comprehensive look at various aspects of... read more

Tutorial: GraphQL Typename

GraphQL typename is a powerful feature that plays a crucial role in programming. From understanding the GraphQL type system and schema to exploring introspection and... read more

Implementing Upsert Operation in GraphQL

Implementing the upsert operation in GraphQL programming involves understanding the purpose of a GraphQL mutation, defining data structure with a GraphQL schema, and the... read more

Exploring Solid GraphQL

GraphQL has revolutionized the way web developers build and consume APIs. In this article, we take an in-depth look at Solid GraphQL and explore its use and benefits in... read more