Introduction to Interfaces

In GraphQL, interfaces are a powerful way to define a set of fields that multiple types can implement. This allows for more flexible and reusable schemas. Interfaces help in creating a polymorphic schema where different types can be queried through a common interface.

Key Concepts

  • Interface Definition: An interface defines a set of fields that a type must include.
  • Type Implementation: Types that implement an interface must include the fields defined by the interface.
  • Querying Interfaces: You can query fields on an interface and get results from any type that implements the interface.

Defining Interfaces

To define an interface in GraphQL, you use the interface keyword followed by the name of the interface and the fields it includes.

interface Character {
  id: ID!
  name: String!
  friends: [Character]
}

In this example, the Character interface includes three fields: id, name, and friends.

Implementing Interfaces

Types that implement an interface must include all the fields defined by the interface. Here’s how you can define types that implement the Character interface:

type Human implements Character {
  id: ID!
  name: String!
  friends: [Character]
  homePlanet: String
}

type Droid implements Character {
  id: ID!
  name: String!
  friends: [Character]
  primaryFunction: String
}

In this example, both Human and Droid types implement the Character interface. They include the id, name, and friends fields, and also have their own specific fields (homePlanet for Human and primaryFunction for Droid).

Querying Interfaces

When querying an interface, you can request fields that are common to all types implementing the interface. You can also use inline fragments to request fields specific to a particular type.

{
  characters {
    id
    name
    ... on Human {
      homePlanet
    }
    ... on Droid {
      primaryFunction
    }
  }
}

In this query, characters is a field that returns a list of Character interface types. The query requests the id and name fields (common to all Character types) and uses inline fragments to request homePlanet for Human and primaryFunction for Droid.

Practical Example

Let's create a simple GraphQL schema with an interface and types implementing it.

Schema Definition

interface Character {
  id: ID!
  name: String!
  friends: [Character]
}

type Human implements Character {
  id: ID!
  name: String!
  friends: [Character]
  homePlanet: String
}

type Droid implements Character {
  id: ID!
  name: String!
  friends: [Character]
  primaryFunction: String
}

type Query {
  characters: [Character]
}

Resolvers

const resolvers = {
  Query: {
    characters: () => [
      { id: '1', name: 'Luke Skywalker', homePlanet: 'Tatooine', friends: [], __typename: 'Human' },
      { id: '2', name: 'R2-D2', primaryFunction: 'Astromech', friends: [], __typename: 'Droid' }
    ]
  },
  Character: {
    __resolveType(character) {
      if (character.homePlanet) {
        return 'Human';
      }
      if (character.primaryFunction) {
        return 'Droid';
      }
      return null;
    }
  }
};

In this example, the __resolveType function is used to determine the type of a Character at runtime.

Exercises

Exercise 1: Define an Interface

Define an interface Vehicle with the fields id, name, and speed.

Solution

interface Vehicle {
  id: ID!
  name: String!
  speed: Int!
}

Exercise 2: Implement the Interface

Create two types, Car and Bike, that implement the Vehicle interface. Add a specific field numWheels to Car and type to Bike.

Solution

type Car implements Vehicle {
  id: ID!
  name: String!
  speed: Int!
  numWheels: Int!
}

type Bike implements Vehicle {
  id: ID!
  name: String!
  speed: Int!
  type: String!
}

Exercise 3: Query the Interface

Write a query to fetch id, name, and speed for all vehicles, and also fetch numWheels for Car and type for Bike.

Solution

{
  vehicles {
    id
    name
    speed
    ... on Car {
      numWheels
    }
    ... on Bike {
      type
    }
  }
}

Conclusion

Interfaces in GraphQL provide a way to define a set of fields that multiple types can implement, allowing for more flexible and reusable schemas. By understanding how to define, implement, and query interfaces, you can create more powerful and maintainable GraphQL APIs. In the next topic, we will explore Unions, which offer another way to handle polymorphic types in GraphQL.

© Copyright 2024. All rights reserved