Unions
Unions define a type that must be exactly one of several possible variants. There are two types of unions:
- Union expressions
- Named unions
Union expressions
Section titled âUnion expressionsâUnnamed unions, or union expressions, can be declared by combining the variants using the | operator.
alias Breed = Beagle | GermanShepherd | GoldenRetriever;In this example, Breed can be either a Beagle, a GermanShepherd, or a GoldenRetriever.
Named unions
Section titled âNamed unionsâNamed unions allow you to assign a name to the union and provide explicit variant references. Named unions are somewhat similar to enums, but instead of having string or numeric values, they use record models.
A named union can be declared with the union keyword. Its name must be an identifier.
union Breed { beagle: Beagle, shepherd: GermanShepherd, retriever: GoldenRetriever,}The above example is equivalent to the Breed alias mentioned earlier, with the difference that emitters can recognize Breed as a named entity and also identify the beagle, shepherd, and retriever names for the options. This format also allows the application of decorators to each of the options.
Constraining a union with extends
Section titled âConstraining a union with extendsâA named union can declare a base type with the extends keyword. Every variant of the union must be assignable to that base type, otherwise a diagnostic is reported on the offending variant.
model Dog { name: string;}model Beagle extends Dog { huntingSkill: string;}model GermanShepherd extends Dog { guardingSkill: string;}
union Breed extends Dog { beagle: Beagle, shepherd: GermanShepherd,}This serves two purposes:
- It prevents a common class of mistake where an unrelated type is accidentally added to a union.
- It records the common base type in the type graph, which makes it easy for emitters to represent the union with a polymorphic base type in languages that donât support unions natively.
The base type does not become a variant of the union. Breed above still has exactly two variants.
extends is a constraint, not a declaration of inheritance. A variant only needs to be assignable to the base type, it doesnât have to explicitly extend it:
model Dog { name: string;}model Beagle { name: string; huntingSkill: string;}
// Ok: `Beagle` is assignable to `Dog` even though it doesn't explicitly extend it.union Breed extends Dog { beagle: Beagle,}The base expression must resolve to a model, scalar, enum, or union. This includes union, intersection, array, and template expressions that resolve to one of those data types. Anonymous model expressions cannot be used directly or through an alias.
union OperationStatus extends string { "Running", "Succeeded", "Failed",}extends also has no interaction with the @discriminator decorator.