kotlinbeginner

Value Classes and Type Aliases

Use value classes for type-safe wrappers without runtime overhead and type aliases for readability.

kotlin
@JvmInline
value class UserId(val value: String) {
    init { require(value.isNotBlank()) { "UserId must not be blank" } }
}

@JvmInline
value class Email(val value: String) {
    init { require(value.contains("@")) { "Invalid email: $value" } }
    val domain: String get() = value.substringAfter("@")
}

@JvmInline
value class Money(val cents: Long) {
    val dollars: Double get() = cents / 100.0
    operator fun plus(other: Money) = Money(cents + other.cents)
    operator fun minus(other: Money) = Money(cents - other.cents)
    operator fun times(factor: Int) = Money(cents * factor)
    override fun toString() = "$$dollars"
}

fun Money(dollars: Double) = Money((dollars * 100).toLong())

typealias UserName = String
typealias Callback<T> = (T) -> Unit
typealias Predicate<T> = (T) -> Boolean
typealias JsonObject = Map<String, Any?>

// Type-safe IDs prevent mixing up parameters
fun findUser(id: UserId): String = "User(${id.value})"
fun sendEmail(to: Email, subject: String) {
    println("Sending '$subject' to ${to.value} (domain: ${to.domain})")
}

fun main() {
    val userId = UserId("user-123")
    val email = Email("alice@example.com")
    println(findUser(userId))
    sendEmail(email, "Welcome!")

    val price = Money(29.99)
    val tax = Money(2.40)
    val total = price + tax
    println("Price: $price + Tax: $tax = Total: $total")
    println("3x: ${price * 3}")

    val onClick: Callback<String> = { println("Clicked: $it") }
    val isAdult: Predicate<Int> = { it >= 18 }
    onClick("button")
    println("Is 20 adult? ${isAdult(20)}")
}

Use Cases

  • Type-safe domain primitives without runtime cost
  • Preventing parameter swapping bugs
  • Readable function signatures with type aliases

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.