This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

Add an Interface to a GraphQL Schema

5:18 JavaScript lesson by

As we start building out more complex GraphQL schemas, certain fields start to repeat across different types. This is a perfect use-case for the Interface Type made available to us through GraphQL’s Type System. In this video, we’ll go over how to create an Interface Type and how to add it to an existing type in a GraphQL Schema.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

As we start building out more complex GraphQL schemas, certain fields start to repeat across different types. This is a perfect use-case for the Interface Type made available to us through GraphQL’s Type System. In this video, we’ll go over how to create an Interface Type and how to add it to an existing type in a GraphQL Schema.

Avatar
Sébastien

Great series so far, but this specific part was unclear to me. I thought an interface could be meant to factorize code and avoid repeating types, but 'fields' still has 'id', there was no change there. So I assume instead it is to make sure that a field 'id' has the same contract among all the GraphQLObjectType that use that same interface (here NodeInterface). The resolveType function still confused me, why do you need to test for 'title' and return videoType? How is it re-usable if you hard code the type?

In reply to egghead.io
Avatar
Josh Black

Hi Sébastien! First off, wanted to say thanks for watching 😄

I thought an interface could be meant to factorize code and avoid repeating types, but 'fields' still has 'id', there was no change there.

Totally understand the confusion here, and sorry for not explaining it clearly enough!

The goal of a GraphQL Interface is to express what fields are shared across the types that implement that interface. In the example with id here, the goal of the Interface is to specify that all types that implement that Interface have an id field with the GraphQLID type.

Unfortunately, the interface doesn't act as a way to re-use existing code. For example, let's say we have the following types in our GraphQL Schema:

interface Name {
  name: String!
}

type Person implements Name {
  name: String!
  firstName: String!
  lastName: String!
}

type Animal implements Name {
  name: String!
  # Some other fields go here...
}

In this case, Person and Animal both implement the Name interface. Getting the name for an animal should just be a simple lookup in our database. However, for a Person the name field could be a combination of their firstName and lastName field.

As a result, we can't share the resolve methods for this field, and so sharing what we've defined in an Interface won't actually satisfy how we want to resolve the fields on each type that has implemented that interface.

Hope this helps explain the role of an Interface a little bit more. If not, I can definitely elaborate!

In reply to Sébastien
Avatar
utkarsh

Really enjoying the course :)
Based on your reply to Sebastien, the interface exists more as a validation to ensure that a particular type is implementing the interface (example id of type GraphQLID) correctly? Thanks!

In reply to Josh Black
Avatar
Josh Black

Hi utkarsh! Glad to hear you're enjoying it! 😄 And yupp, that's exactly it (from my perspective).

In reply to utkarsh

Currently in our GraphQL schema, we have a video type. This video type has a field called ID. This field is of type GraphQL ID and it's interesting, because if we were to add another type to our GraphQL schema, such as an instructor type, we might also want that instructor type to have the same field.

When we want to describe a set of possible fields that a type could have, we would use something called a GraphQL interface type. To create this interface, let's go and create a Node.js file inside of source/node.js.

Next, we'll open that file and start importing a couple of things. First, we'll make sure to grab a GraphQL interface type since we are creating an interface.

We'll also grab GraphQL a non-null and GraphQL ID to describe the ID field on this interface. Then, we'll just require all of these from the GraphQL package.

Next up, we'll define our actual interface, which we're calling "Node Interface," and this is just a new GraphQL interface type. Inside of the constructor, we can give it a name, in this case Node.

Then, we'll also describe all of the fields that are available on types that use this interface, in this case, we will define ID. The type of this ID will be a new GraphQL non-null GraphQL ID. The last thing that we're going to do is just export our interface using module to export, and then passing in Node interface.

Now, we can switch back into our index.js file and import this Node interface at the bottom of our definitions here. We'll do, "Const nodeinterface=require," and then, we'll pass in /source/node.

Now, we can go find our video type which is down here, and we can add in our interfaces at the bottom of the definition here. We'll say interfaces and pass in an array.

We'll just add in that Node interface as the first part of that array of interfaces. The goal for this interface is to be able to use it anytime we have shared fields between types.

Say, we were defining an instructor type which would be a new GraphQL object type. Then inside of here, we knew that the fields for this would also contain this ID field, as well.

Since we're sharing these fields, we would also add the interfaces array once again and pass in the Node interface as the first element of that array.

This is guaranteeing that these two types that share the same fields now have a common interface that they both implement. Let's get rid of this instructor type, since we are not actually using it and try and run our current server using Node index.js.

What we get is actually an error, because our interface type Node doesn't actually provide a way for that interface to know what type it's working with when we're trying to resolve that field.

Let's go and fix this error by switching back into our text editor of choice, and then going to source/node.js. Inside of here, we're going to add a method called Result type. This is going to be a function that takes in an object.

What we're going to do is check to see if this object has a title, then we're going to return video type. We'll import that in a second, otherwise, we don't know what type it is, we'll just return null.

To get this video type, we need to make sure that we're exporting it. Inside of index.js at the end of our video type definition, and it's going to do exports.videotype=videotype.

Then, we'll switch back into Node.js and import at the top. Const videotype is going to be equal to require, and then, we'll just put in the path to the index.js file.

Now that we've imported our video type and we've made sure to add a resolve type method, let's go and try to rerun our server to see if there's any more issues.

We'll do Node index.js. We see that we have a new error here, but here, we're just saying that node.id is expecting the non-null GraphQL ID type, but what we're putting in the video type right now is just a GraphQL ID. This is just saying that our given type video is not actually following the interface that it is implementing.

To fix this, let's hop back into our index.js file and instead of saying that the video type has a field that just has a type for GraphQL ID. We're going to say, "New GraphQL non-null," to make sure that it matches our interface. We'll pass in GraphQL ID.

Now with this new type definition, let's go back to our server and try and run it. It looks like we're good to go.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?