Skip to main content

Unions

Similar to enums, Unions are restricted to a set of predefined variants, however the possible types are always the more complex GraphQLObjectType.

Per the GraphQL spec, Unions can't be (or be part of) Input types and their possible types is a non empty collection of unique GraphQLObjectType.

GraphQL Specification

To have the following GraphQL type definitions:

union ModelEvent = ModelAdded | ModelRemoved

type ModelRemoved {
"The removed model id"
modelId: ID!
}

type ModelAdded {
model: Model!
}

type Model {
id: ID!
}

You could provide this definitions:

import 'package:leto_schema/leto_schema.dart';

final model = objectType(
'Model',
fields: [
graphQLIdType.nonNull().field('id'),
],
);
final modelAddedGraphQLType = objectType(
'ModelAdded',
fields: [model.nonNull().field('model')],
);
final modelRemovedGraphQLType = objectType(
'ModelRemoved',
fields: [graphQLIdType.nonNull().field('modelId')],
);

final union = GraphQLUnionType(
// name
'ModelEvent',
// possibleTypes
[
modelAddedGraphQLType,
modelRemovedGraphQLType,
],
);
  • extractInner

When the members of the union type are not

Freezed Unions

With code generation, Unions with freezed also work without trouble.

import 'package:leto_schema/leto_schema.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

()
class Model {
final String id;

const Model(this.id);
}

()

class ModelEvent with _$ModelEvent {
const factory ModelEvent.added(Model model) = ModelAdded;
const factory ModelEvent.removed(
(type: 'graphQLIdType', description: 'The removed model id')
String modelId,
// you can also provide a private class
) = _ModelRemoved;
}
GraphQLAttachments unionNoFreezedAttachments() => const [ElementComplexity(50)];

(unionNoFreezedAttachments)
(
description: '''
Description from annotation.

Union generated from raw Dart classes''',
)
(name: 'UnionNoFreezedRenamed')
class UnionNoFreezed {
const factory UnionNoFreezed.a(String value) = UnionNoFreezedA.named;
const factory UnionNoFreezed.b(int value) = UnionNoFreezedB;
}

()
class UnionNoFreezedA implements UnionNoFreezed {
final String value;

const UnionNoFreezedA.named(this.value);
}

()
class UnionNoFreezedB implements UnionNoFreezed {
final int value;

const UnionNoFreezedB(this.value);
}

()
List<UnionNoFreezed> getUnionNoFrezzed() {
return const [UnionNoFreezed.a('value'), UnionNoFreezed.b(12)];
}