I’m glad that Scala 3 introduced unions (and intersections), but I’ve just discovered there’s no narrowing and no support for structural typing.
The following would work both in Python (pyright / mypy) and TypeScript:
def f1(x: Int | String) = x match
case _: String => "str"
case i => String(i + 3) // no narrowing
def f2(x: Int | String) =
if x.isInstanceOf[String] then
"str"
else
String(x + 3) // no narrowing
class A(val x: Int)
class B(val x: Int)
def f3(x: A | B): Int =
x.x // no structural typing
Narrowing is not that useful in the simple cases above, as it actually interferes with exhaustiveness checking, but it’s a good feature to have in more complex scenarios involving type guards and nested logic.
Structural typing is also kind of nice, especially when working with unions.
Of course, Scala has tons of features Python doesn’t have or I wouldn’t even consider leaving Python for Scala.