Idiomatic union type

To identify i use Id or Name.
Is code below idiomatic scala, or would you do it differently?

// Identify by name or id
object Test:
  case class Name(name: String)
  case class Id(id: Int)

  type NameOrId = Name | Id

  def main(args:Array[String])=

    def convert(id: NameOrId):String =
      id match
        case Name(name) => name
        case Id(id)   => id.toString
    end convert

    val x:NameOrId=Id(5)
    val y:NameOrId=Name("Fred")
  end main
end Test

The way you’re using it here there isn’t any advantage over using inheritance:

object Test {
  trait NameOrId {}
  case class Name(name: String) extends NameOrId {
    override def toString = name
  case class Id(id: Int) extends NameOrId {
    override def toString = id.toString
  def main(args: Array[String]) =
    val x: NameOrId = Id(5)
    val y: NameOrId = Name("Fred")
    println(s"ID = $x")
    println(s"Name = $y")

If you don’t control Name or Id, though, type unions give you a way to do it (the way you show is fine). It’s also possible to use Either if you want more monadic-style operations.

Thanks. The drawback of Either is that it only works for 2 or nesting.
And i wanted the “conversion functions” grouped together.

If you are using Scala3 you have union types. However, what I think you want are opaque types. More verbose to code, but does not incur the cost of boxing. For Scala2 the equivalent are AnyVal, however it does not guarantee the value remains “unboxed”.