My experience migrating a PlayFramework app to Scala 3
I have a small PlayFramework app (https://superintendent.app), which was on Scala 2. I've decided to migrate this app to Scala 3. Here are my learnings:
The goods
- Scala 2 syntax is still valid in Scala 3. Basically, 95% of the code still works as-is.
- Cross-publishing one of my libraries to work with Scala 3 took maybe 15 minutes. SBT seems stable and robust these days.
- I used
TypeTag
, which has been removed in Scala 3. I've randomly decided to tell AI to rewrite it without rewriting it withoutTypeTag
, and it did correctly:

I prompted it to use izumi-reflect
because I thought we needed it. It turns out we don't need it, and AI did it correctly. That AI moment was magical.
The obstacles
- The
unapply
of a case class has been effectively removed.
It took me a while to find a replacement (link):
object Tuples:
def to[A <: Product](value: A)(
using mirror: Mirror.ProductOf[A]
): mirror.MirroredElemTypes = Tuple.fromProductTyped(value)
def from[A](value: Product)(
using
mirror: Mirror.ProductOf[A],
ev: value.type <:< mirror.MirroredElemTypes
): A = mirror.fromProduct(value)
// Tuples.to[YourCaseClass] is equivalent to YourCaseClass.unapply.
//
// If your case class has only 1 parameter, then Tuples.to[YourCaseClass] would output a tuple of one. This is the only difference.
- Enum isn't as flexible nor powerful as Sealed Abstract Class
Obviously, but this took me maybe an hour to rewrite the implicits that we had for the original Sealed Abstract Class.
extension
doesn't work with Enum, so I had to flip the method from an implicit conversion to a regular method that took an enum value as the first parameter.
I've also learned that we cannot overwrite name
if our enum
extends the Java's Enum
.
scala.reflect.runtime
has been mostly removed.
ClassTag
still exists. This enables us to use Java's reflection.
However, TypeTag
has been removed. This means we cannot utilize knownDirectSubclasses
, for example.
izumi-reflect
seems like a good replacement but you will have to learn the library. I didn't because it turned out I don't need it. Java's reflection suffices for my need.