Is it possible to specify a type that implements multiple interfaces within a GraphQL schema? If so, how would this be accomplished?
An interface cannot implement another interface.
Yes, it is possible. This is the catch: java does not support multiple inheritance, i.e. class cannot extend more than one class. However class can implement multiple interfaces.
Like many type systems, GraphQL supports interfaces. An Interface is an abstract type that includes a certain set of fields that a type must include to implement the interface. For example, you could have an interface Character that represents any character in the Star Wars trilogy: interface Character { id: ID!
GraphQL interfaces are useful to solve problems like above where we want to have the returned type possibly from different types. For this to work, we can define a Union type that can resolve to either one of Book , Movie or Album and then each type can have its own set of fields.
Yes. As outlined in the spec:
An object type may declare that it implements one or more unique interfaces.
Keep in mind that the resulting object must be a "super-set of all interfaces it implements" -- it must implement all the fields each interface has and these fields cannot conflict. For example, if Interface A and Interface B both have a field called something
, the type of that field must be the same for both interfaces in order for an Object Type to implement both interfaces.
Here's a simple example that you can open in CodeSandbox and play around with.
Note: As others have pointed out, using a comma to separate the interfaces is no longer supported -- please use an &
(ampersand) instead.
const { ApolloServer, gql } = require("apollo-server");
const typeDefs = gql`
type Query {
someAnimal: Animal!
someBird: Bird!
}
interface Bird {
wingspan: Int!
}
interface Animal {
speed: Int!
}
type Swallow implements Animal & Bird {
wingspan: Int!
speed: Int!
}
`;
const resolvers = {
Query: {
someAnimal: (root, args, context) => {
return { wingspan: 7, speed: 24 };
},
someBird: (root, args, context) => {
return { wingspan: 6, speed: 25 };
}
},
Bird: {
__resolveType: () => "Swallow"
},
Animal: {
__resolveType: () => "Swallow"
}
};
const server = new ApolloServer({
typeDefs,
resolvers
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
Please note that the spec now also allows interfaces to implement other interfaces.
When defining an interface that implements another interface, the implementing interface must define each field that is specified by the implemented interface... Transitively implemented interfaces (interfaces implemented by the interface that is being implemented) must also be defined on an implementing type or interface.
In GraphQL.js, this is supported as of version 15.0.0.
It seems comma separating the interfaces doesn't work anymore. I had to use "&" instead to make it work (Apollo), see this answer https://stackoverflow.com/a/49521662/1959584
type Something implements First & Second
I think yes, it should be possible as the specification describes on http://facebook.github.io/graphql/June2018/#sec-Interfaces.
Here is the example.
interface NamedEntity {
name: String
}
interface ValuedEntity {
value: Int
}
type Person implements NamedEntity {
name: String
age: Int
}
type Business implements NamedEntity & ValuedEntity {
name: String
value: Int
employeeCount: Int
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With