Scala.js-specific runtime library components for Scala 3, providing JavaScript-specific functionality and bridge components between Scala 3 and the Scala.js runtime environment
—
Mirror-based generic programming for automatic derivation of type class instances, supporting both sum types (enums) and product types (case classes).
Core mirror types for compile-time reflection and generic programming.
/**
* Base trait for compile-time reflection of types
* Provides type-level access to the structure of enums, case classes, and objects
*/
sealed trait Mirror:
/** The type being mirrored */
type MirroredMonoType
/** String name of the mirrored type */
type MirroredLabel <: String
/** Tuple of element names (field names for products, case names for sums) */
type MirroredElemLabels <: Tuple
/**
* Mirror for sum types (sealed traits, enums)
* Provides ordinal access to sum type variants
*/
trait Mirror.Sum extends Mirror:
/** Get ordinal (index) of sum type instance */
def ordinal(x: MirroredMonoType): Int
/**
* Mirror for product types (case classes, tuples)
* Provides construction from generic product representation
*/
trait Mirror.Product extends Mirror:
/** Element types of the product */
type MirroredElemTypes <: Tuple
/** Create instance from product representation */
def fromProduct(p: scala.Product): MirroredMonoType
/**
* Mirror for singleton types (objects, case objects)
*/
trait Mirror.Singleton extends Mirror.Product:
type MirroredElemTypes = EmptyTuple
def fromProduct(p: scala.Product): MirroredMonoType
/**
* Mirror proxy for Scala 2 compatibility
*/
trait Mirror.SingletonProxy extends Mirror.SingletonType Aliases:
object Mirror:
/** Mirror of any kind for type T */
type Of[T] = Mirror { type MirroredMonoType = T }
/** Product mirror for type T */
type ProductOf[T] = Mirror.Product { type MirroredMonoType = T }
/** Sum mirror for type T */
type SumOf[T] = Mirror.Sum { type MirroredMonoType = T }Usage Examples:
import scala.deriving.Mirror
// Example types
enum Color:
case Red, Green, Blue
case class Person(name: String, age: Int)
case object Singleton
// Using mirrors
def showStructure[T](value: T)(using mirror: Mirror.Of[T]): String =
val typeName = constValue[mirror.MirroredLabel]
s"Type: $typeName"
// Sum type mirror
def getOrdinal[T](value: T)(using mirror: Mirror.SumOf[T]): Int =
mirror.ordinal(value)
val red = Color.Red
println(getOrdinal(red)) // 0
// Product type mirror
def fromTuple[T](tuple: Tuple)(using mirror: Mirror.ProductOf[T]): T =
mirror.fromProduct(tuple.asInstanceOf[Product])
val personTuple = ("Alice", 30)
val person = fromTuple[Person](personTuple.asInstanceOf[Tuple])Common patterns for writing generic code using mirrors.
// Type class derivation pattern
trait Show[T]:
def show(value: T): String
object Show:
/** Derive Show for product types */
inline def derived[T](using mirror: Mirror.ProductOf[T]): Show[T] =
new Show[T]:
def show(value: T): String =
val typeName = constValue[mirror.MirroredLabel]
val elemLabels = constValueTuple[mirror.MirroredElemLabels]
// Implementation details...
s"$typeName(...)"
/** Derive Show for sum types */
inline def derived[T](using mirror: Mirror.SumOf[T]): Show[T] =
new Show[T]:
def show(value: T): String =
val typeName = constValue[mirror.MirroredLabel]
val ordinal = mirror.ordinal(value)
s"$typeName#$ordinal"Usage Examples:
// Automatic derivation
case class Point(x: Double, y: Double) derives Show
enum Status derives Show:
case Active, Inactive, Pending
// Using derived instances
val point = Point(1.0, 2.0)
println(summon[Show[Point]].show(point)) // "Point(...)"
val status = Status.Active
println(summon[Show[Status]].show(status)) // "Status#0"
// Manual derivation
given Show[Person] = Show.derived
val alice = Person("Alice", 30)
println(summon[Show[Person]].show(alice))Advanced patterns for complex generic programming scenarios.
// Recursive derivation for nested structures
trait Eq[T]:
def eqv(x: T, y: T): Boolean
object Eq:
given Eq[String] = _ == _
given Eq[Int] = _ == _
given Eq[Boolean] = _ == _
given [T](using eq: Eq[T]): Eq[Option[T]] =
(x, y) => (x, y) match
case (Some(a), Some(b)) => eq.eqv(a, b)
case (None, None) => true
case _ => false
given [T](using eq: Eq[T]): Eq[List[T]] =
(xs, ys) => xs.length == ys.length && xs.zip(ys).forall(eq.eqv)
inline def derived[T](using mirror: Mirror.Of[T]): Eq[T] =
inline mirror match
case m: Mirror.SumOf[T] => derivedSum(using m)
case m: Mirror.ProductOf[T] => derivedProduct(using m)
private inline def derivedSum[T](using mirror: Mirror.SumOf[T]): Eq[T] =
(x, y) => mirror.ordinal(x) == mirror.ordinal(y) && x == y
private inline def derivedProduct[T](using mirror: Mirror.ProductOf[T]): Eq[T] =
(x, y) =>
val xProduct = Tuple.fromProductTyped(x)
val yProduct = Tuple.fromProductTyped(y)
compareProducts(xProduct, yProduct)
private def compareProducts[T <: Tuple](x: T, y: T): Boolean =
// Implementation for comparing tuple elements recursively
x == y // SimplifiedUsage Examples:
// Derive equality for complex nested types
case class Address(street: String, city: String)
case class Person(name: String, age: Int, address: Address) derives Eq
val alice1 = Person("Alice", 30, Address("Main St", "NYC"))
val alice2 = Person("Alice", 30, Address("Main St", "NYC"))
val bob = Person("Bob", 25, Address("Oak Ave", "LA"))
println(summon[Eq[Person]].eqv(alice1, alice2)) // true
println(summon[Eq[Person]].eqv(alice1, bob)) // falseUtilities for working with tuples in generic programming.
object Tuple:
/** Convert any Product to a tuple with proper typing */
def fromProductTyped[P <: Product](p: P): Tuple =
fromProduct(p).asInstanceOf[Tuple]
/** Convert Product to untyped tuple */
def fromProduct(p: Product): Tuple =
// Convert product to tuple representation
???
/** Get size of tuple type at compile time */
inline def size[T <: Tuple]: Int = constValue[Size[T]]
/** Map over tuple with type-level function */
inline def map[T <: Tuple, F[_]](tuple: T)(f: [X] => X => F[X]): Map[T, F] = ???Usage Examples:
// Working with products as tuples
case class Point3D(x: Double, y: Double, z: Double)
val point = Point3D(1.0, 2.0, 3.0)
val tuple = Tuple.fromProductTyped(point) // (1.0, 2.0, 3.0)
// Type-level size computation
type Coords = (Double, Double, Double)
val size = Tuple.size[Coords] // 3
// Type-level mapping
val optionalCoords = Tuple.map((1.0, 2.0, 3.0))(
[X] => (x: X) => Option(x)
) // (Some(1.0), Some(2.0), Some(3.0))Working with compile-time labels and names.
/**
* Extract field names from a mirror as a tuple of strings
*/
inline def labelValues[T](using mirror: Mirror.Of[T]): Tuple =
constValueTuple[mirror.MirroredElemLabels]
/**
* Get type name as string
*/
inline def typeName[T](using mirror: Mirror.Of[T]): String =
constValue[mirror.MirroredLabel]Usage Examples:
case class User(id: Int, name: String, email: String)
// Get field names at compile time
val fieldNames = labelValues[User] // ("id", "name", "email")
val className = typeName[User] // "User"
// Use in generic serialization
def toMap[T](value: T)(using mirror: Mirror.ProductOf[T]): Map[String, Any] =
val labels = labelValues[T].toArray.map(_.toString)
val values = Tuple.fromProductTyped(value).toArray
labels.zip(values).toMap
val user = User(1, "Alice", "alice@example.com")
val userMap = toMap(user)
// Map("id" -> 1, "name" -> "Alice", "email" -> "alice@example.com")Seamless integration with common type class patterns.
// Common derivable type classes work automatically
trait Ordering[T]:
def compare(x: T, y: T): Int
trait Encoder[T]:
def encode(value: T): String
trait Decoder[T]:
def decode(input: String): Either[String, T]
// Standard derives syntax works
case class Product(name: String, price: Double)
derives Eq, Show, Ordering, Encoder, Decoder
enum Priority derives Eq, Show, Ordering:
case Low, Medium, High// Core mirror types
sealed trait Mirror:
type MirroredMonoType
type MirroredLabel <: String
type MirroredElemLabels <: Tuple
trait Mirror.Sum extends Mirror:
def ordinal(x: MirroredMonoType): Int
trait Mirror.Product extends Mirror:
type MirroredElemTypes <: Tuple
def fromProduct(p: scala.Product): MirroredMonoType
trait Mirror.Singleton extends Mirror.Product:
type MirroredElemTypes = EmptyTuple
trait Mirror.SingletonProxy extends Mirror.Singleton
// Type aliases
object Mirror:
type Of[T] = Mirror { type MirroredMonoType = T }
type ProductOf[T] = Mirror.Product { type MirroredMonoType = T }
type SumOf[T] = Mirror.Sum { type MirroredMonoType = T }Install with Tessl CLI
npx tessl i tessl/maven-org-scala-lang--scala3-library-sjs1-3