scalabeginner
Type Aliases and Abstract Types
Define type aliases, abstract types, and type members for cleaner and more expressive APIs.
scalaPress ⌘/Ctrl + Shift + C to copy
// Simple type aliases
type UserId = Long
type Username = String
type Email = String
type Timestamp = Long
// Function type aliases
type Predicate[A] = A => Boolean
type Transform[A] = A => A
type Handler[A, B] = A => Either[String, B]
type AsyncHandler[A, B] = A => scala.concurrent.Future[B]
// Complex generic aliases
type Result[A] = Either[String, A]
type Validated[A] = Either[List[String], A]
type Parser[A] = String => Result[A]
// Using aliases for cleaner signatures
def findUser(id: UserId): Result[Username] =
if id > 0 then Right(s"User-$id")
else Left("Invalid user ID")
def validateAge: Handler[String, Int] = input =>
input.toIntOption match
case Some(age) if age >= 0 && age <= 150 => Right(age)
case Some(age) => Left(s"Age out of range: $age")
case None => Left(s"Not a number: $input")
def isAdult: Predicate[Int] = _ >= 18
def double: Transform[Int] = _ * 2
// Abstract type members
trait Container:
type Elem
type Collection[_]
def get(index: Int): Option[Elem]
def size: Int
class IntListContainer(items: List[Int]) extends Container:
type Elem = Int
type Collection[A] = List[A]
def get(index: Int): Option[Int] = items.lift(index)
def size: Int = items.length
class StringArrayContainer(items: Array[String]) extends Container:
type Elem = String
type Collection[A] = Array[A]
def get(index: Int): Option[String] = items.lift(index)
def size: Int = items.length
// Path-dependent types
trait Database:
type Row
type Query
def execute(q: Query): List[Row]
class PostgresDB extends Database:
case class PgRow(data: Map[String, Any])
type Row = PgRow
type Query = String
def execute(q: String): List[PgRow] =
List(PgRow(Map("result" -> q)))
@main def run(): Unit =
// Type aliases in action
println(findUser(1))
println(findUser(-1))
println(validateAge("25"))
println(validateAge("abc"))
println(s"Is 20 adult: ${isAdult(20)}")
println(s"Double 5: ${double(5)}")
// Containers
val intContainer = IntListContainer(List(10, 20, 30))
val strContainer = StringArrayContainer(Array("a", "b", "c"))
println(s"Int[1]: ${intContainer.get(1)}")
println(s"Str[2]: ${strContainer.get(2)}")
// Database
val db = PostgresDB()
val rows = db.execute("SELECT * FROM users")
println(s"Rows: $rows")
// Chaining with aliases
val pipeline: List[Transform[Int]] = List(_ + 1, _ * 2, _ - 3)
val result = pipeline.foldLeft(10)((acc, f) => f(acc))
println(s"Pipeline result: $result")Use Cases
- Simplifying complex type signatures
- Domain-specific type vocabulary
- Abstract type members for flexibility
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
scalaintermediate
Refined and Constrained Types
Create constrained types with validation: non-empty strings, bounded numbers, and validated domain types.
Best for: Domain type validation
#scala#refined
scalabeginner
Type Conversions and Safe Casting
Convert between types safely: numeric conversions, asInstanceOf alternatives, and pattern-based casting.
Best for: Safe data type conversions
#scala#types
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