I encountered them quite soon, e.g. something like this [1]:
val result: Int | "INTERNAL_SERVER_ERROR" = 1
val m: Int = result match {
case "INTERNAL_SERVER_ERROR" => throw new Exception("Uh oh")
case t => t
}
It does work with a ClassTag and t: T, but then it thinks the match is not exhaustive. Compare that to Typescript [2].
In this specific language feature TS is kinda the gold standard. For example they can automatically narrow the type based on fields existing or not and their type, which can be used to provide a pretty decent implementation of sum types [3]
[1] https://scastie.scala-lang.org/oMdkLBIiRsqUkXv6qbP61g
[2] https://www.typescriptlang.org/play?#code/MYewdgzgLgBATgUwgV...
[3] https://www.typescriptlang.org/docs/handbook/unions-and-inte...