J'ai défini l'énumération suivante dans TypeScript:
enum Color{
Red, Green
}
Maintenant, dans ma fonction, je reçois la couleur sous forme de chaîne. J'ai essayé le code suivant:
var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum
Comment puis-je convertir cette valeur en une énumération?
Les énumérations dans TypeScript 0.9 sont basées sur une chaîne + un nombre. Vous ne devriez pas avoir besoin d'assertion de type pour les conversions simples:
enum Color{
Red, Green
}
// To String
var green: string = Color[Color.Green];
// To Enum / number
var color : Color = Color[green];
J'ai de la documentation sur cela et sur d'autres modèles Enum dans mon livre OSS: https://basarat.gitbooks.io/TypeScript/content/docs/enums.html
A partir de TypeScript 2.1, les clés de chaîne sont fortement typées. keyof typeof
est utilisé pour obtenir des informations sur les clés de chaîne disponibles ( 1 ):
enum Color{
Red, Green
}
let typedColor: Color = Color.Green;
let typedColorString: keyof typeof Color = "Green";
// Error "Black is not assignable ..." (indexing using Color["Black"] will return undefined runtime)
typedColorString = "Black";
// Error "Type 'string' is not assignable ..." (indexing works runtime)
let letColorString = "Red";
typedColorString = letColorString;
// Works fine
typedColorString = "Red";
// Works fine
const constColorString = "Red";
typedColorString = constColorString
// Works fine (thanks @SergeyT)
let letColorString = "Red";
typedColorString = letColorString as keyof typeof Color;
typedColor = Color[typedColorString];
https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types
Cette note se rapporte à réponse de Basarat, pas à la question initiale.
J'ai eu un problème étrange dans mon propre projet où le compilateur donnait une erreur à peu près équivalente à "ne peut pas convertir une chaîne en couleur" en utilisant l'équivalent de ce code:
var colorId = myOtherObject.colorId; // value "Green";
var color: Color = <Color>Color[colorId]; // TSC error here: Cannot convert string to Color.
J'ai trouvé que l'inférence du type de compilateur devenait confuse et elle pensait que colorId
était une valeur enum et non un ID. Pour résoudre le problème, je devais convertir l'ID sous forme de chaîne:
var colorId = <string>myOtherObject.colorId; // Force string value here
var color: Color = Color[colorId]; // Fixes lookup here.
Je ne suis pas sûr de la cause du problème, mais je laisserai cette note ici au cas où quelqu'un rencontrerait le même problème que moi.
Si vous êtes certain qu'une chaîne d'entrée a une correspondance exacte avec Color enum, utilisez:
const color: Color = (<any>Color)["Red"];
Dans le cas où une chaîne d'entrée peut ne pas correspondre à Enum, utilisez:
const mayBeColor: Color | undefined = (<any>Color)["WrongInput"];
if (mayBeColor !== undefined){
// TypeScript will understand that mayBeColor is of type Color here
}
Si nous ne convertissons pas enum
en <any>
, alors TypeScript affichera l'erreur:
L'élément a implicitement le type 'any' car l'expression d'index n'est pas du type 'number'.
Cela signifie que par défaut, le type TypeScript Enum fonctionne avec les index numériques, c'est-à-dire let c = Color[0]
, mais pas avec les index de chaîne tels que let c = Color["string"]
. Il s'agit d'une restriction connue de l'équipe Microsoft pour le problème plus général Index de chaînes d'objets.
Je l'ai obtenu en utilisant le code suivant.
var green= "Green";
var color : Color= <Color>Color[green];
J'ai aussi rencontré la même erreur de compilation. Juste une légère variation plus courte de l'approche de Sly_cardinal.
var color: Color = Color[<string>colorId];
Si le compilateur TypeScript sait que le type de variable est string, cela fonctionne:
let colorName : string = "Green";
let color : Color = Color[colorName];
Sinon, vous devriez explicitement le convertir en chaîne (pour éviter les avertissements du compilateur):
let colorName : any = "Green";
let color : Color = Color["" + colorName];
Au moment de l'exécution, les deux solutions fonctionneront.
enum Color{
Red, Green
}
// To String
var green: string = Color[Color.Green];
// To Enum / number
var color : Color = Color[green as keyof typeof Color]; //Works with --noImplicitAny
Cet exemple fonctionne avec --noImplicitAny
dans TypeScript
Sources:
https://github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229https://www.typescriptlang.org/docs/handbook/advanced -types.html # index-types
Il y a beaucoup d'informations mitigées dans cette question, couvrons donc toute l'implémentation de TypeScript 2.x + dans Guide de Nick sur l'utilisation d'énums dans les modèles avec TypeScript.
Ce guide est destiné aux personnes qui créent un code côté client qui englobe un ensemble de chaînes connues du serveur, qui serait commodément modélisé sous la forme d’un Enum du côté client.
Commençons par l'énum. Ça devrait ressembler a quelque chose comme ca:
export enum IssueType {
REPS = 'REPS',
FETCH = 'FETCH',
ACTION = 'ACTION',
UNKNOWN = 'UNKNOWN',
}
Deux choses à noter ici:
Nous les déclarons explicitement comme des cas d'énumération adossés à des chaînes, ce qui nous permet de les instancier avec des chaînes, pas avec d'autres nombres non liés.
Nous avons ajouté une option qui n'existe peut-être pas sur notre modèle de serveur: UNKNOWN
. Ceci peut être traité comme undefined
si vous préférez, mais j'aime éviter les types | undefined
autant que possible pour simplifier la gestion.
Le grand avantage d'avoir un cas UNKNOWN
est que vous pouvez être vraiment évident à ce sujet dans le code et créer des styles pour des cas d'enum inconnus de couleur rouge vif et clignotant, de sorte que vous sachiez que vous ne gérez pas quelque chose correctement.
Vous utilisez peut-être cette énumération incorporée dans un autre modèle, ou toute seule, mais vous devrez analyser l'énumération chaîne-y de JSON ou XML (ha) dans votre contrepartie fortement typée. Lorsqu'il est incorporé à un autre modèle, cet analyseur réside dans le constructeur de classe.
parseIssueType(typeString: string): IssueType {
const type = IssueType[typeString];
if (type === undefined) {
return IssueType.UNKNOWN;
}
return type;
}
Si l'énumération est correctement analysée, elle finira par être du type approprié. Sinon, ce sera undefined
et vous pourrez l'intercepter et renvoyer votre cas UNKNOWN
. Si vous préférez utiliser undefined
comme cas inconnu, vous pouvez simplement renvoyer tout résultat de l'analyse syntaxique tentée.
À partir de là, il suffit d'utiliser la fonction d'analyse et d'utiliser votre nouvelle variable typée forte.
const strongIssueType: IssueType = parseIssueType('ACTION');
// IssueType.ACTION
const wrongIssueType: IssueType = parseIssueType('UNEXPECTED');
// IssueType.UNKNOWN
J'avais besoin de savoir comment boucler les valeurs d'énum (je testais beaucoup de permutations de plusieurs énumérations) et j'ai trouvé que cela fonctionnait bien:
export enum Environment {
Prod = "http://asdf.com",
Stage = "http://asdf1234.com",
Test = "http://asdfasdf.example.com"
}
Object.keys(Environment).forEach((environmentKeyValue) => {
const env = Environment[environmentKeyValue as keyof typeof Environment]
// env is now equivalent to Environment.Prod, Environment.Stage, or Environment.Test
}
Enum
enum MyEnum {
First,
Second,
Three
}
tilisation de l'échantillon
const parsed = Parser.parseEnum('FiRsT', MyEnum);
// parsed = MyEnum.First
const parsedInvalid= Parser.parseEnum('other', MyEnum);
// parsedInvalid = undefined
Ignorer l'analyse sensible à la casse
class Parser {
public static parseEnum<T>(value: string, enumType: T): T[keyof T] | undefined {
if (!value) {
return undefined;
}
for (const property in enumType) {
const enumMember = enumType[property];
if (typeof enumMember === 'string') {
if (enumMember.toUpperCase() === value.toUpperCase()) {
const key = enumMember as string as keyof typeof enumType;
return enumType[key];
}
}
}
return undefined;
}
}
Essaye ça
var color: Color = (Couleur comme tout) ["Vert];
Cela fonctionne bien pour la version 3.5.3
Les énumérations créées de cette manière sont compilées dans un objet qui stocke à la fois les mappages forward (name -> value)
et inverses (value -> name)
. Comme nous pouvons le constater à partir de cette capture d'écran chrome devtools:
Voici un exemple du fonctionnement de la double correspondance et de la conversion de l'une à l'autre:
enum Color{
Red, Green
}
// To Number
var greenNr: number = Color['Green'];
console.log(greenNr); // logs 1
// To String
var greenString: string = Color[Color['Green']]; // or Color[Color[1]
console.log(greenString); // logs Green
// In your example
// recieve as Color.green instead of the string green
var green: string = Color[Color.Green];
// obtain the enum number value which corresponds to the Color.green property
var color: Color = (<any>Color)[green];
console.log(color); // logs 1