How to make an Scala Enumeration implement a Trait without modifying the original Enum?

351 Views Asked by At

I'm toying with Scala for the first time so bear with me. Also using tapir to declare an API, where I'm having issues providing a Schema for an enum.

I have a bunch of enums defined that are part of my domain model and that extend Scala's Enumeration. For instance, this is one of them:

object Status extends Enumeration with JsonEnumeration {
    val Active, Completed, Archived, Deleted = Value
}

And also have many case classes that uses them. For instance, Order uses our previously defined enumeration, like:

case class Order(
    id: String,
    name: Option[String],
    status: Status.Value,
)

I want to make this enum implement a trait that adds an implicit, but without modifying the original Status enumeration (I don't want to couple the Status enum -and all the others- to this trait).

The trait looks like:

import sttp.tapir.{Schema, Validator}

trait TapirEnumeration { e: Enumeration =>
  implicit def schemaForEnum: Schema[e.Value] =
    Schema.string.validate(Validator.enumeration(e.values.toList, v => Option(v)))
}

I wanted to somehow modify the Order object so the Status enum is now a TapirStatus enum (or something like that) which extends both the original Status and TapirEnumeration, but I don't think that can be doable, given that Status is originally defined as a companion object.

Ideally, all the enums I want to expose as responses from my API will implement that TapirEnumeration trait while still extending what they already extend.

What can I do to achieve this? Of course, creating a new enum that implements the trait isn't DRY so it's not an option.

1

There are 1 best solutions below

6
On

Why does implicit need to be defined in the enum itself in the first place? Just make it its own definition.

import scala.language.implicitConversions
object EnumImplicits {
    implicit def schema[E <: Enumeration](e: E): Schema[e.Value] = ???
}

Then, wherever you need access to that implicit you just make it available with import EnumImplicits._

Here is an example