# Union and Intersection Types in Scala 3

Scala 3 aka dotty comes with a lot of new types. Union, Intersection , Opaque etc. Let’s understand **union** and **intersection** types in detail.

# Union types

A union type `A | B`

represents a type that has values of type `A`

or `B`

at a given time. A pattern match must be performed at the point of usage to extract the exact type.

This would not have been possible in Scala 2. We would have to create a super type for our types and then create the method with the super type.

## Rules for Union types

- Union types are commutative i.e
`A | B`

is same as`B | A`

. `A`

and`B`

are sub types of`A | B`

for all values of`A`

and`B`

- Co- Variance rules for Union types : Given a co-variant type
`C`

then`C[A] | C[B] <: C[A | B]`

Basically we can pass a `List[Int]`

and a `List[String]`

to a method expecting a `List[Int|String]`

. This makes `C[A]`

and `C[B]`

a sub type of `C[A|B]`

.

Also we can pass `List[String]|List[Int]`

type where a `List[String|Int]`

is expected. This makes `C[A] | C[B]`

a sub type of `C[A|B]`

. However the reverse is not possible as seen in line 24.

- Contra-variance rules for Union types : Given a contra variant type C then
`C[A | B] <: C[A]`

and`C[A | B] <: C[B]`

Here, we see that we could pass a `Printer[String|Int]`

where a `Printer[Int]`

was required.

# Intersection types

A intersection type `A & B`

represents a type that has values of type `A`

and`B`

at the same time.

At line 8 we are able to use both methods from intersection type i.e `monoid`

contains the functionality of both Semigroup and Indentity types. The intersection type will also act as a type restriction, so we need to mix in both traits if we are to use this method properly.

## Rules for Intersection types

- Intersection types are commutative i.e
`A & B`

is same as`B & A`

. - Given any types
`A`

and`B`

,`A & B`

is a sub type for both`A`

and`B`

- Co- Variance rules for Intersection types : Given a co-variant type
`C`

then`C[A & B] <: C[A] & C[B]`

Here, we see that we can provide an `Option[TwitterPost & InstagramPost]`

when we need a `Option[TwitterPost]`

or a `Option[InstagramPost]`

. This also leads us to the fact that when we need an `Option[TwitterPost] & Option[InstagramPost]`

we can provide a `Option[TwitterPost & InstagramPost]`

.

- Given a contra-variant type
`C`

a`C[A |B]`

is a sub type of`C[A] & C[B]`

What happens here is that a `Printer`

instance which knows how to print `Int|String`

can be passed when we need a `Printer[Int] & Printer[String]`

. This is exactly what is done is line 15.

- what happens the two intersected types share a method signature except the returned types?

Here both `Singer`

and `Dancer`

types have a method called `share`

with the same signature but different return types. An intersection type of these two upon calling the `share`

method must return both an `InstagramPost`

and a `TwitterPost`

. The only type that can do that is an intersection i.e `TwitterPost & InstagramPost`

.

# Conclusion

We explored Union and Intersection types in Scala 3 and checked how these types work with variance rules in Scala. Checkout the official dotty docs for further reading