scalaintermediate
Union and Intersection Types
Use Scala 3 union and intersection types for flexible and precise type definitions.
scalaPress ⌘/Ctrl + Shift + C to copy
// Union types: A | B
def processInput(input: String | Int | Double): String = input match
case s: String => s"String: $s"
case i: Int => s"Int: $i"
case d: Double => s"Double: $d"
// Union in return type
def divide(a: Int, b: Int): Int | String =
if b == 0 then "Division by zero"
else a / b
// Error types with union
case class NotFound(id: String)
case class Forbidden(reason: String)
case class BadRequest(message: String)
type ApiError = NotFound | Forbidden | BadRequest
def handleError(error: ApiError): (Int, String) = error match
case NotFound(id) => (404, s"Not found: $id")
case Forbidden(reason) => (403, s"Forbidden: $reason")
case BadRequest(msg) => (400, s"Bad request: $msg")
// Intersection types: A & B
trait Printable:
def print(): String
trait Serializable:
def serialize(): Array[Byte]
trait Validatable:
def isValid: Boolean
case class Document(title: String, content: String)
extends Printable with Serializable with Validatable:
def print(): String = s"[$title] $content"
def serialize(): Array[Byte] = s"$title|$content".getBytes
def isValid: Boolean = title.nonEmpty && content.nonEmpty
// Function requiring intersection
def processDocument(doc: Printable & Serializable & Validatable): String =
if doc.isValid then
val printed = doc.print()
val bytes = doc.serialize()
s"Valid: $printed (${bytes.length} bytes)"
else
"Invalid document"
// Structural types
type HasName = { def name: String }
type HasAge = { def age: Int }
type Person = HasName & HasAge
@main def run(): Unit =
// Union types
println(processInput("hello"))
println(processInput(42))
println(processInput(3.14))
// Return union
val r1 = divide(10, 3)
val r2 = divide(10, 0)
println(s"10/3 = $r1")
println(s"10/0 = $r2")
// API errors
val errors: List[ApiError] = List(
NotFound("user-123"),
Forbidden("insufficient permissions"),
BadRequest("missing required field")
)
errors.map(handleError).foreach { (code, msg) =>
println(s" $code: $msg")
}
// Intersection
val doc = Document("README", "Hello World")
println(processDocument(doc))
val emptyDoc = Document("", "")
println(processDocument(emptyDoc))Use Cases
- Flexible function parameters
- Typed error handling
- Composable interface requirements
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
scalaintermediate
Given Imports and Exports
Manage given instances with Scala 3 import syntax: selective imports, exports, and priorities.
Best for: Organizing type class instances
#scala#given
scalaintermediate
Multiversal Equality in Scala 3
Use strict equality with CanEqual to prevent comparing unrelated types at compile time.
Best for: Preventing accidental type comparisons
#scala#equality
scalabeginner
Scala Hello World Application
Create a basic Scala application with main method, string interpolation, and val/var basics.
Best for: Getting started with Scala
#scala#basics
scalabeginner
Pattern Matching Fundamentals
Use Scala pattern matching with guards, type patterns, tuple patterns, and nested extractors.
Best for: Control flow with pattern matching
#scala#pattern-matching