Support for "string type enum" and automatic type checking for the string

Topics: Language Specification
Jun 20, 2014 at 10:31 AM
Edited Jun 28, 2014 at 5:12 AM
(I think this was discussed somewhere but I couldn't find it...)

Sometimes I want to do this:
enum Characters {
    Madoka = "madoka",
    Homura = "homura",
    Sayaka = "sayaka",
    Kyouko = "kyouko",
    Mami = "mami",
    Nagisa = "nagisa",
    Kyubey = "kyubey"
}
Why do I want to use strings, not just playing comfortable with number enumeration?
enum Characters {
    Madoka,
    Homura,
    Sayaka,
    Kyouko,
    Mami,
    Nagisa,
    Kyubey
}
C# users absolutely won't bother to put strings, because there really is no difference! However, I'm in JavaScript area, and I want to allow both of these, especially when I make a general JS library:
class Foo {
    static getCharacter(c: Characters) {
        ...
    }
}

Foo.getCharacter(Characters.Madoka); // using enum
Foo.getCharacter("madoka"); // using plain string
The first example is the traditional use of enum in typed language, and the second one is the traditional use of enum in JavaScript, which is just a plain string here. Really? Yes: xhr.open("GET", "http://typescriptlang.org/", true) - no XMLHttpRequestMethod.GET but just "GET" here.

Okay, maybe the second one is more traditional in JS. So what would be better using plain string?

First: Simply, the second one has shorter and more compact code length. Yeah!
Somebody would say: "Wait, wait. What we really want here is a strong type, not stringed type! Longer code is just a tradeoff here!" However, what if TS actively check if the string is in the required enum type, which is Characters here?
Foo.getCharacter("madoka"); // Correct!
Foo.getCharacter("sasuke"); // No, no... you're wrong. That's not in the list.
An automatic type checking would collaborate greatly with string type enum.

Second: Any additional converter will not be required.
For example, string type enum can be easily used out of JS. What? Would you ever use enum in CSS? Maybe.
div[data-character=madoka] {
    background-color: #F7BBC3;
}
div[data-character=homura] {
    background-color: #6C6B69;
}
div[data-character=sayaka] {
    background-color: #87B1C1;
}
div[data-character=kyouko] {
    background-color: #B05F6E;
}
div[data-character=mami] {
    background-color: #F6DF93;
}
div[data-character=nagisa] {
    background-color: #754A20;
}
div[data-character=kyubey] {
    background-color: #F8F3F9;
}
I'm just giving only background-color property here, but one would give more in once, to switch them easily by changing data-character. Anyway, This would require a enum-to-string converter:
setCharacter(div: HTMLDivElement, c: Character) {
    div.dataset.character = this.enumToString(c);

    ...
}

private enumToString(c: Characters) {
    switch (c) {
        case Characters.Madoka:
            return "madoka";
        case Characters.Homura:
            return "homura";
        case Characters.Sayaka:
            return "sayaka";
        case Characters.Kyouko:
            return "kyouko";
        case Characters.Mami:
            return "mami";
        case Characters.Nagisa:
            return "nagisa";
        case Characters.Kyubey:
            return "kyubey";
    }
}
However, with the string type enum, this would be much easier, without any converter.
setCharacter(div: HTMLDivElement, c: Character) {
    div.dataset.character = c; // Simple!

    ...
}
So... I'd like to see this:
  1. Allowing string in enum
  2. Automatically checking type from string for the string type enum
I think this would make my life easier. What do you think? :) Well, maybe this is not an 'enum-eration' anymore.
Jun 20, 2014 at 2:57 PM
See here: https://typescript.codeplex.com/workitem/1217
(There is a work around for now there also)
Jun 20, 2014 at 3:21 PM
Yeah, the compiler just compiles string type, still giving error. (I didn't know the workaround. Thank you!)
What I suggest here is to support this officially, and to fully benefit from this string type by automatically checking enum type from string. Isn't it cool? ;)

Thank you again for the proper reference :)
Jun 21, 2014 at 9:07 AM
Edited Jun 28, 2014 at 5:12 AM
I read the post and I agree that string type enum can be helpful for overloads.
enum Characters {
    Madoka,
    Homura,
    Sayaka,
    Kyouko,
    Mami,
    Nagisa,
    Kyubey
}

class GameCenter {
    createCharacter(charType: "madoka"): MadokaObject 
    createCharacter(charType: "homura"): HomuraObject
    createCharacter(charType: "sayaka"): SayakaObject
    createCharacter(charType: "kyouko"): KyoukoObject
    createCharacter(charType: "mami"): MamiObject
    createCharacter(charType: "nagisa"): NagisaObject
    createCharacter(charType: "kyubey"): KyubeyObject
    createCharacter(charType: Characters): any
    createCharacter(charType: Characters) {
        //...
    }
    //...
}

var madoka = gameCenter.createCharacter("madoka");
madoka.moveBy([1,1]);
Here, the parameter types are still specified by string, but a string type enum will confine them to the specific list, and an IDE may provide auto-completion for convenience. Overloading here will be more clean as the strings are actually strongly typed by language.

Furthermore, a string type enum here will not permit any other unspecified string, so the library users would feel more comfortable when they call the method.
Jun 28, 2014 at 9:16 PM
Edited Jun 28, 2014 at 9:30 PM
Let's note that WebIDL also uses string type enum ;) http://www.w3.org/TR/2013/WD-WebCryptoAPI-20130625/#key-interface
enum KeyType {
  "secret",
  "public",
  "private"
};

enum KeyUsage {
  "encrypt",
  "decrypt",
  "sign",
  "verify",
  "derive",
  "wrap",
  "unwrap"
};

interface Key {
  readonly attribute KeyType type;
  readonly attribute bool extractable;
  readonly attribute Algorithm algorithm;
  readonly attribute KeyUsage[] keyUsage;
};
The WebIDL syntax requires string value only, which seems better as one doesn't have to write similar name twice.

Meanwhile, current TypeScript declaration uses just plain string.
interface Key {
    algorithm: Algorithm;
    type: string;
    extractable: boolean;
    keyUsage: string[];
}
Aug 13, 2014 at 4:09 PM
@SaschaNaz - Interesting that this example use Web Crypto, as I was trying to do exactly this - limit KeyType to one of "public", "private" or "secret".

Have you created more of the Crypto interface? It would be great to get submitted back into https://github.com/borisyankov/DefinitelyTyped/tree/master/webcrypto