# 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