Tapuscrit `enum` de chaîne JSON

Est-il possible d'avoir un Tapuscrit enum compatible avec les chaînes à partir de JSON?

Par exemple:

enum Type { NEW, OLD }

interface Thing { type: Type }

let thing:Thing = JSON.parse('{"type": "NEW"}');

alert(thing.type == Type.NEW); //false

Je comme thing.type == Type.NEW pour être vrai. Ou plus précisément, je souhaite que je pourrais spécifier le enum de valeurs définie comme chaînes, pas des numéros.

Je suis conscient que je peux utiliser thing.type.toString() == Type[Type.NEW] mais c'est gênant, et semble faire l'enum type d'annotation confuse et trompeuse, qui va à l'encontre de son but. Le JSON est techniquement pas de la fourniture d'un valide valeur d'enum, donc je ne devrais pas le type de la propriété de l'enum.

Donc ce que je suis en train de faire à la place est à l'aide d'un type de chaîne avec des constantes statiques:

const Type = { NEW: "NEW", OLD: "OLD" }

interface Thing { type: string }

let thing:Thing = JSON.parse('{"type": "NEW"}');

alert(thing.type == Type.NEW); //true

Cela me met à l'utilisation que je veux, mais le type d'annotation string est trop large et sujettes à erreur.

Je suis un peu surpris qu'un sur-ensemble de JavaScript n'a pas de chaîne en fonction des enums. Ai-je raté quelque chose? Est-il une manière différente de ce qui peut être fait?


Mise à jour 1.8 TS

À l'aide de un littéral de chaîne types est une autre alternative (merci @basaret), mais pour obtenir les enum-de l'utilisation (ci-dessus), il nécessite de définir vos valeurs deux fois: une fois dans une chaîne de caractères littérale type, et une fois en tant que valeur (constante ou de l'espace):

type Type = "NEW" | "OLD";
const Type = {
    NEW: "NEW" as Type,
    OLD: "OLD" as Type
}

interface Thing { type: Type }

let thing:Thing = JSON.parse(`{"type": "NEW"}`);

alert(thing.type === Type.NEW); //true

Cela fonctionne, mais prend beaucoup de passe-partout, assez que je ne l'utilise pas, la plupart du temps. Pour l'instant, je suis en espérant que le proposition de string enum finira par faire de la feuille de route.


Mise à jour TS 2.1

La nouvelle keyof type de recherche permet à la chaîne de type de littéral à être généré à partir des touches de const ou de l'espace, ce qui rend la définition d'un peu moins redondants:

namespace Type {
    export const OLD = "OLD";
    export const NEW = "NEW";
}
type Type = keyof typeof Type;

interface Thing { type: Type }

const thing: Thing = JSON.parse('{"type": "NEW"}');
thing.type == Type.NEW //true

Mise à jour TS 2.4

Tapuscrit 2.4 ajout du support pour la chaîne enums! L'exemple ci-dessus devient:

enum Type {
    OLD = "OLD",
    NEW = "NEW"
}

interface Thing { type: Type }
const thing: Thing = JSON.parse('{"type": "NEW"}');
alert(thing.type == Type.NEW) //true

Cela ressemble près de parfait, mais il y a encore quelques chagrin d'amour:

  • Vous encore avoir à écrire la valeur de deux fois, c'est à dire OLD = "OLD", et il n'y a pas de validation que vous n'avez pas une faute de frappe, comme NEW = "MEW"... cela a déjà mordu moi, dans le code réel.
  • Il y a quelques "bizarreries" (peut-être des bugs?) avec la façon dont le type enum est vérifié, ce n'est pas juste une chaîne littérale type de sténographie, qui est ce qui serait vraiment correctes. Certains problèmes que j'ai rencontré en:

    enum Color { RED = "RED", BLUE = "BLUE", GREEN = "GREEN" }
    
    type ColorMap = { [P in Color]: number; }
    
    declare const color: Color;
    declare const map: ColorMap;
    map[color] //Error: Element implicitly has an 'any' type because type 'ColorMap' has no index signature.
    
    const red: Color = "RED"; //Type '"RED"' is not assignable to type 'Color'.
    const blue: Color = "BLUE" as "RED" | "BLUE" | "GREEN"; //Error: Type '"RED" | "BLUE" | "GREEN"' is not assignable to type 'Color'.

    Le code équivalent avec enum Color remplacé par un littéral de chaîne types de bien fonctionner...

Ouais, je pense que j'ai des TOC à ce sujet, je veux juste mon parfait JS enums. 🙂

InformationsquelleAutor Aaron Beall | 2016-03-02