Is it possible to wrap the members types with another type in Scala 3 similar to typescript mapped types?

Viewed 65

In typescript it looks like this

type Option<T> = {some: T} | 'none'
type Optional<T> = {
  [P in keyof T]: Option<T[P]>
};
type Foo = {x: string, y: number}
type OptionalFoo = Optional<Foo>
const foo: OptionalFoo = {x: 'none', y : {some: 123}}
case class Foo(x: String, y: Int)

I would like to have

type OptionalFoo = Optional[Foo] == case class OptionalFoo(x: Option[String], y: Option[Int])

Is it possible to achive something like this in Scala 3?

1 Answers

If you do not care about the names of each field, you could perhaps do this:

type Foo = (String, Int)
type Optional[T <: Tuple] = Tuple.Map[T, Option]
type OptionalFoo = Optional[Foo]

val optionalFoo: OptionalFoo = (Some("foobar"), None)
optionalFoo match {
  case (x, y) => println(s"x is $x, y is $y")
}

Scastie

This may have been possible in Scala 2, which supported annotation macros. Perhaps type class derivation may also help you here. Shapeless also has many useful mechanisms if you do not care about actually creating a completely new case class.

Related