Как мне преобразовать строку в enum в TypeScript?
Я определил следующее перечисление в TypeScript:
enum Color{
Red, Green
}
Теперь в моей функции я получаю цвет в виде строки. Я пробовал следующий код:
var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum
Как я могу преобразовать это значение в перечисление?
Ответы
Ответ 1
Перечисления в TypeScript 0.9 основаны на строках и цифрах. Вам не нужно вводить утверждение типа для простых преобразований:
enum Color{
Red, Green
}
// To String
var green: string = Color[Color.Green];
// To Enum / number
var color : Color = Color[green];
Попробуйте в Интернете
У меня есть документация об этом и других шаблонах Enum в моей книге OSS: https://basarat.gitbooks.io/typescript/content/docs/enums.html
Ответ 2
Как из Typescript 2.1 строковые ключи в перечислениях строго типизированы. keyof typeof
используется для получения информации о доступных строковых клавишах (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
Ответ 3
Эта заметка относится к basarat answer, а не к исходному вопросу.
У меня была странная проблема в моем собственном проекте, где компилятор сообщал ошибку, примерно эквивалентную "невозможно преобразовать строку в цвет", используя эквивалент этого кода:
var colorId = myOtherObject.colorId; // value "Green";
var color: Color = <Color>Color[colorId]; // TSC error here: Cannot convert string to Color.
Я обнаружил, что вывод метода компилятора сбился с толку, и он думал, что colorId
является значением перечисления, а не идентификатором. Чтобы устранить проблему, я должен был указать идентификатор в виде строки:
var colorId = <string>myOtherObject.colorId; // Force string value here
var color: Color = Color[colorId]; // Fixes lookup here.
Я не уверен, что вызвало проблему, но я оставлю это примечание здесь, если кто-то столкнется с той же проблемой, что и я.
Ответ 4
Если вы уверены, что входная строка точно совпадает с Color enum, используйте:
const color: Color = (<any>Color)["Red"];
В случае, если входная строка может не соответствовать Enum, используйте:
const mayBeColor: Color | undefined = (<any>Color)["WrongInput"];
if (mayBeColor !== undefined){
// TypeScript will understand that mayBeColor is of type Color here
}
площадка
Если мы не приведем тип enum
к типу <any>
, тогда TypeScript покажет ошибку:
Элемент неявно имеет тип 'any', потому что индексное выражение не относится к типу 'number'.
Это означает, что по умолчанию тип TypeScript Enum работает с числовыми индексами, т.е.
let c = Color[0]
, но не со строковыми индексами, такими как let c = Color["string"]
. Это известное ограничение команды Microsoft для более общей проблемы Индексы строк объекта.
Ответ 5
Я получил его с помощью следующего кода.
var green= "Green";
var color : Color= <Color>Color[green];
Ответ 6
Я также столкнулся с той же ошибкой компилятора. Просто небольшая вариация подхода Sly_ Cardinal.
var color: Color = Color[<string>colorId];
Ответ 7
Если компилятор TypeScript знает, что тип переменной - строка, это работает:
let colorName : string = "Green";
let color : Color = Color[colorName];
В противном случае вы должны явно преобразовать его в строку (чтобы избежать предупреждений компилятора):
let colorName : any = "Green";
let color : Color = Color["" + colorName];
Во время выполнения оба решения будут работать.
Ответ 8
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
Этот пример работает с --noImplicitAny
в TypeScript
Источники:
https://github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229 https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types
Ответ 9
В этом вопросе много смешанной информации, поэтому давайте рассмотрим всю реализацию для TypeScript 2. x+ в Руководстве Ника по Использованию Enums в моделях с TypeScript.
Это руководство предназначено для: тех, кто создает код на стороне клиента, который принимает от сервера набор известных строк, который будет удобно моделироваться как Enum на стороне клиента.
Определить перечисление
Давайте начнем с перечисления. Это должно выглядеть примерно так:
export enum IssueType {
REPS = 'REPS',
FETCH = 'FETCH',
ACTION = 'ACTION',
UNKNOWN = 'UNKNOWN',
}
Здесь следует отметить две вещи:
-
Мы явно объявляем их как регистры перечисления со строковыми данными, что позволяет нам создавать их экземпляры со строками, а не с некоторыми другими не связанными числами.
-
Мы добавили параметр, который может существовать или не существовать в нашей модели сервера: UNKNOWN
. Это может быть обработано как undefined
если вы предпочитаете, но я хотел бы избежать | undefined
| undefined
типы по возможности, чтобы упростить обработку.
UNKNOWN
случая UNKNOWN
является то, что вы можете быть действительно очевидны в коде и делать стили для неизвестных перечисляемых случаев ярко-красными и мигающими, чтобы вы знали, что вы что-то неправильно обрабатываете.
Разобрать перечисление
Возможно, вы используете это перечисление, встроенное в другую модель, или все в одиночку, но вам придется проанализировать перечисление со строковым типом y из JSON или XML (ха) в свой строго типизированный аналог. Встраиваемый в другую модель, этот синтаксический анализатор живет в конструкторе класса.
parseIssueType(typeString: string): IssueType {
const type = IssueType[typeString];
if (type === undefined) {
return IssueType.UNKNOWN;
}
return type;
}
Если перечисление правильно проанализировано, оно в конечном итоге будет иметь правильный тип. В противном случае оно будет undefined
и вы можете перехватить его и вернуть свой UNKNOWN
случай. Если вы предпочитаете использовать undefined
качестве неизвестного случая, вы можете просто вернуть любой результат из попытки анализа enum.
Оттуда, это только вопрос использования функции анализа и использования вашей новой строго типизированной переменной.
const strongIssueType: IssueType = parseIssueType('ACTION');
// IssueType.ACTION
const wrongIssueType: IssueType = parseIssueType('UNEXPECTED');
// IssueType.UNKNOWN
Ответ 10
Мне нужно было знать, как перебирать значения перечислений (тестировал множество перестановок нескольких перечислений), и я обнаружил, что это хорошо работает:
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
}
Ответ 11
Я искал ответ, который мог бы получить enum
из string
, но в моем случае значения перечислений имели разные строковые значения. У ОП было простое перечисление для Color
, но у меня было что-то другое:
enum Gender {
Male = 'Male',
Female = 'Female',
Other = 'Other',
CantTell = "Can't tell"
}
Когда вы пытаетесь разрешить Gender.CantTell
с помощью строки "Can't tell"
, он возвращает undefined
с исходным ответом.
Еще один ответ
По сути, я придумал другой ответ, вдохновленный этим ответом:
export const stringToEnumValue = <ET, T>(enumObj: ET, str: string): T =>
(enumObj as any)[Object.keys(enumObj).filter(k => (enumObj as any)[k] === str)[0]];
Notes
- Мы берем первый результат
filter
, предполагая, что клиент передает допустимую строку из перечисления. Если это не так, будет возвращено undefined
.
- Мы приводим
enumObj
к any
, потому что с TypeScript 3. 0+ (в настоящее время используется TypeScript 3.5), enumObj
разрешается как unknown
.
Пример использования
const cantTellStr = "Can't tell";
const cantTellEnumValue = stringToEnumValue<typeof Gender, Gender>(Gender, cantTellStr);
console.log(cantTellEnumValue); // Can't tell
Примечание: И, как кто-то указал в комментарии, я также хотел использовать noImplicitAny
.
Ответ 12
Enum
enum MyEnum {
First,
Second,
Three
}
Пример использования
const parsed = Parser.parseEnum('FiRsT', MyEnum);
// parsed = MyEnum.First
const parsedInvalid= Parser.parseEnum('other', MyEnum);
// parsedInvalid = undefined
Игнорировать регистрозависимый анализ
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;
}
}
Ответ 13
Попробуйте это
var color: Color = (Color as any)["Green];
Это прекрасно работает для версии 3.5.3
Ответ 14
Перечисления, созданные так, как вы это сделали, скомпилированы в объект, в котором хранятся как прямые (name → value)
и обратные (value → name)
отображения. Как мы можем наблюдать из этого скриншота Chrome Devtools:
![enter image description here]()
Вот пример того, как работает двойное сопоставление и как приводить от одного к другому:
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