Hacker News new | ask | show | jobs
by nicktelford 1855 days ago
No. It's a Singleton type, which means that instead of just being a String, it has to be exactly the String "Scala".

i.e.

val x: "scala" = "scala" // would compile

val y: "scala" = "java" // would produce a compile error

Union types are an orthogonal concept, and work as you'd expect:

val z: String | Int = "foo"

1 comments

Interesting, and I presume it works for singletons of any type, correct?

    val x: 1 = 1
    val y: 2.718281828 = 2.718281828
That's kind of cute. I presume its main purpose is for overrides in order to get something similar to template specialization. C++ templates can be specialized by types and by values, but Scala method overrides are only by type, and literal types allow you to present a value as a type, so if the value can be statically proven to match, then the override is called?
In TypeScript perhaps the most important use case for literal types is the ability to to create discriminated unions, or algebraic datatypes (ADTs). Many modern languages have a separate feature for this (such as enums in Rust), but in TypeScript they can be constructed using literal and union types. Here's an example:

    interface ProductOffer { 
        kind: 'productOffer'
        eans: Ean[]
        discountPercentage: number
    }

    interface GroupOffer {
        kind: 'groupOffer'
        groups: GroupId[]
        discountPercentage: number
    }

    type Offer = ProductOffer | GroupOffer

Also check the TypeScript handbook for more information: https://www.typescriptlang.org/docs/handbook/2/narrowing.htm...
I think it is important to emphasize that there is actually an important difference.

Union types don't allow to model GADTs, so they are less powerful than what some other languages offer. But on the other side, they allow for much easier composition. E.g.:

type Citrus = "Orange" | "Lemon" type Prunus = "Plum" | "Apricot"

Now in typescript you can just do:

type Fruit = Citrus | Prunus

But in many other languages it's not so easy and you have to jump through hoops and e.g. either redefine the types and/or refactor the code (if you can even do that - if the code is from 3rd party libraries you are out of luck).

It's not really about specialization (types in Scala tend to be parametric most of the time) so much as just being able to have values in types, so that you can have types like "ListOfLength[1]" or "MapContainingKeys["Foo" :: "Bar" :: Nil]" without having to do some horrendous encoding of those things as types.