Interfaces

A GraphQL interface defines a set of fields that multiple object types share. When a field returns an interface type, the client can query the shared fields directly and use fragments to access type-specific fields. Interfaces are output-only types and cannot be used as arguments or input fields.

GraphQL schema

GraphQL
interface Message {
author: User!
createdAt: DateTime!
}
type TextMessage implements Message {
author: User!
createdAt: DateTime!
content: String!
}
type Query {
messages: [Message]!
}

Client query

GraphQL
{
messages {
createdAt
... on TextMessage {
content
}
}
}

The shared createdAt field is queried directly on the interface. The content field, which exists only on TextMessage, is accessed through an inline fragment.

Defining an Interface Type

Hot Chocolate maps C# interfaces and abstract classes to GraphQL interface types.

C#
// Types/IMessage.cs
[InterfaceType("Message")]
public interface IMessage
{
User Author { get; set; }
DateTime CreatedAt { get; set; }
}
// Types/TextMessage.cs
public class TextMessage : IMessage
{
public User Author { get; set; }
public DateTime CreatedAt { get; set; }
public string Content { get; set; }
}
// Types/MessageQueries.cs
[QueryType]
public static partial class MessageQueries
{
public static IMessage[] GetMessages()
{
// ...
}
}
C#
// Program.cs
builder
.AddGraphQL()
.AddType<TextMessage>();

You must register each implementing type explicitly so Hot Chocolate knows which object types belong to the interface.

You can also use an abstract class instead of an interface:

C#
// Types/Message.cs
[InterfaceType]
public abstract class Message
{
public User Author { get; set; }
public DateTime CreatedAt { get; set; }
}

Ignoring Fields

You can exclude specific fields from the GraphQL interface.

C#
// Types/IMessage.cs
[InterfaceType("Message")]
public interface IMessage
{
[GraphQLIgnore]
User Author { get; set; }
DateTime CreatedAt { get; set; }
}

Overriding Names

Use [GraphQLName] or the Name method to override inferred names.

C#
// Types/IMessage.cs
[GraphQLName("Post")]
public interface IMessage
{
User Author { get; set; }
[GraphQLName("addedAt")]
DateTime CreatedAt { get; set; }
}

You can also specify the name through the [InterfaceType] attribute:

C#
[InterfaceType("Post")]
public interface IMessage

Both produce the following schema:

GraphQL
interface Post {
author: User!
addedAt: DateTime!
}

Interfaces Implementing Interfaces

GraphQL interfaces can implement other interfaces, forming a hierarchy.

C#
// Types/IMessage.cs
[InterfaceType("Message")]
public interface IMessage
{
User Author { get; set; }
}
// Types/IDatedMessage.cs
[InterfaceType("DatedMessage")]
public interface IDatedMessage : IMessage
{
DateTime CreatedAt { get; set; }
}
// Types/TextMessage.cs
public class TextMessage : IDatedMessage
{
public User Author { get; set; }
public DateTime CreatedAt { get; set; }
public string Content { get; set; }
}
C#
// Program.cs
builder
.AddGraphQL()
.AddType<IDatedMessage>()
.AddType<TextMessage>();

Register intermediate interfaces (like DatedMessage) explicitly if they are not returned directly from a resolver field.

Next Steps

Last updated on April 13, 2026 by Michael Staib