Let's say I have this ADT :
case class Person(id: String)
case class Kid(id: String, name: String)
I would like to represent the id field in more explicit and type safe way. I have two options
type PersonId = String
case class Person(id: PersonId)
case class Kid(id: String, name: PersonId)
case class PersonId(id: String) extends AnyVal
case class Person(id: PersonId)
case class Kid(id: String, name: PersonId)
Which approach is more idiomatic? Are there any advantages of using value class in this case (no additional methods)?
Type aliases are purely a syntactic convenience—in some cases they can make code cleaner or easier to refactor, but they don't provide any additional type safety. For example, suppose I've got some code like this:
type DegreesC = Double
type DegreesF = Double
def c2f(c: DegreesC): DegreesF = (c * 9.0 / 5.0) + 32
And a value representing the current temperature in Fahrenheit:
val currentTempInF = 62.0
The compiler is happy to let me pass this to my c2f
method:
scala> c2f(currentTempInF)
res1: DegreesF = 143.6
Value classes give you more type safety without the runtime cost of an additional allocation for the case class (although there is still a syntactic cost):
case class DegreesC(value: Double) extends AnyVal
case class DegreesF(value: Double) extends AnyVal
def c2f(c: DegreesC): DegreesF = DegreesF((c.value * 9.0 / 5.0) + 32)
val currentTempInF = DegreesF(62.0)
And then:
scala> c2f(currentTempInF)
<console>:14: error: type mismatch;
found : DegreesF
required: DegreesC
c2f(currentTempInF)
^
Which you prefer is a matter of taste. Personally I think type aliases in Scala are often overused and oversold, but I also tend to avoid value classes because they have weird limitations and bugs, and the runtime performance benefits they offer often aren't that important to me. In any case I wouldn't say one approach or the other is more idiomatic (if anything I'd give that status to a plain, non-value class case class).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With