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, commeNEW = "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. 🙂
Vous devez vous connecter pour publier un commentaire.
Si vous utilisez la Machine avant de la version 2.4, il y a un moyen de le réaliser avec des enums en jetant les valeurs de votre enum pour
any
.Un exemple de votre première mise en œuvre
Tapuscrit 2.4 a un support intégré de la chaîne des enums déjà, le casting de
any
ne seraient plus nécessaires et que vous pourriez réaliser sans l'utilisation deChaîne de caractères Littérale de l'Union Type
, qui est ok pour la validation et la saisie semi-automatique, mais pas très bon pour des raisons de lisibilité et de refactoring, en fonction du scénario d'utilisation.any
affirmation avant. Maintenant, je suis en train de sortir TS 2.4 chaîne des enums, et c'est assez proche de ce que je voulais... mais j'ai trouvé quelques problèmes avec la façon dont TS les vérifications de type il...any
est assez pour le compilateur pour créer une cartographie inverse. Il serait vraiment utile, si vous pouviez modifier cette info dans ta réponse.TS 2.9.2
Ma solution:
et quand j'ai de la valeur à partir de l'API json:
Convenu. Une solution de contournement rapide (si vous avez le luxe de la génération de code, vous pouvez automatiser ce):
Ceux-ci sont appelés littéraux de chaîne dans un union. Plus : https://basarat.gitbooks.io/typescript/content/docs/tips/stringEnums.html
thing.type == Type.NEW
.Type
et les valeurs à deux reprises, une fois en tant quetype
pour l'utiliser comme un type d'interface d'annotation, et encore comme uneconst
pour des utilisations où j'ai besoin de les valeurs. Cela peut-il être amélioré?J'ai été en utilisant les fonctions du convertisseur, comme un pis-aller. J'espère que ce thread est livré à une résolution: https://github.com/Microsoft/TypeScript/issues/1206