Unions
A union type represents a set of object types. It is very similar to an interface, except that there is no requirement for common fields between the specified types.
SDL
type TextContent { text: String!}
type ImageContent { imageUrl: String! height: Int!}
union PostContent = TextContent | ImageContent
Clients can query fields returning a union like the following.
GraphQL
{ content { ... on TextContent { text } ... on ImageContent { imageUrl } }}
Learn more about unions here.
Usage
Unions can be defined like the following.
We can use a marker interface (or an abstract class) to define object types as part of a union.
C#
[UnionType("PostContent")]public interface IPostContent{}
public class TextContent : IPostContent{ public string Text { get; set; }}
public class ImageContent : IPostContent{ public string ImageUrl { get; set; }
public int Height { get; set; }}
public class Query{ public IPostContent GetContent() { // Omitted code for brevity }}
C#
builder.Services .AddGraphQLServer() .AddQueryType<Query>() .AddType<TextContent>() .AddType<ImageContent>();
C#public class TextContent{ public string Text { get; set; }}
public class TextContentType : ObjectType<TextContent>{}
public class ImageContent{ public string ImageUrl { get; set; }
public int Height { get; set; }}
public class ImageContentType : ObjectType<ImageContent>{}
public class PostContentType : UnionType{ protected override void Configure(IUnionTypeDescriptor descriptor) { descriptor.Name("PostContent");
// The object types that belong to this union descriptor.Type<TextContentType>(); descriptor.Type<ImageContentType>(); }}
public class Query{ public object GetContent() { // Omitted code for brevity }}
public class QueryType : ObjectType<Query>{ protected override void Configure(IObjectTypeDescriptor<Query> descriptor) { descriptor .Field(f => f.GetContent(default)) .Type<PostContentType>(); }}
Since the types are already registered within the union, we do not have to register them again in our Program class.
We can use a marker interface, as in the implementation-first approach, to type our union definition: UnionType<IMarkerInterface>
Last updated on February 17, 2026 by Michael Staib