Я определил следующее перечисление в TypeScript?
enum Color{
Red, Green
}
Теперь в моей функции я получаю цвет в виде строки. Я пробовал следующий код:
var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum
Как я могу преобразовать это значение в перечисление?
Перечисления в 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
Как из 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
let s = "Green"; let typedColor = <keyof typeof Color> s;
let
на const
будет работать без приведения. Обновленный пример, чтобы прояснить это. Спасибо @SergeyT
Эта заметка относится к 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.
Я не уверен, что вызвало проблему, но я оставлю это примечание здесь, если кто-то столкнется с той же проблемой, что и я.
Получил работу с использованием следующего кода.
var green= "Green";
var color : Color= <Color>Color[green];
Если вы уверены, что строка ввода имеет точное совпадение с перечислением цвета, используйте:
const color: Color = (<any>Color)["Red"];
В случае, когда входная строка может не соответствовать использованию Enum:
const mayBeColor: Color | undefined = (<any>Color)["WrongInput"];
if(mayBeColor !== undefined){
//TSC will understand that mayBeColor of type Color here
}
Если мы не используем тип enum
to <any>
, тогда tsc покажет ошибку
Элемент неявно имеет тип "any", потому что выражение индекса не относится к типу "число".
Это означает, что по умолчанию тип TS Enum работает с индексами чисел, т.е.
let c = Color[0]
, но не со строковыми индексами типа let c = Color["string"]
. Это известное ограничение команды Microsoft для более общей проблемы Индексы строковых объектов.
Я также столкнулся с той же ошибкой компилятора. Просто небольшая вариация подхода Sly_ Cardinal.
var color: Color = Color[<string>colorId];
myProp.color = Color[<string><any>myProp.color]
Ура
Если typescript компилятор знает, что тип переменной является строкой, чем это работает
let colorName : string = "Green";
let color : Color = Color[colorName];
в противном случае вы должны явно преобразовать его в строку (чтобы избежать предупреждения компилятора)
let colorName : any = "Green";
let color : Color = Color["" + colorName];
Во время выполнения оба решения будут работать.
<string>colorName
вместо "" + colorName
?
В этом вопросе много смешанной информации, поэтому давайте рассмотрим всю реализацию 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
IssueType["REPS"]="REPS"
. Если бы вы определили свое перечисление немного по-другому, скажем, REPS="reps"
это привело бы к IssueType["REPS"]="reps"
что бы ...
IssueType.UNKNOWN
потому что в вашем перечислении нет ключевых reps
. Жаль, что я до сих пор не нашел рабочего решения для этого, так как мои строки содержат дефисы, которые делают их непригодными в качестве ключей.
--noImplicitAny
(в VS не--noImplicitAny
«Разрешить неявные« любые »типы»).error TS7017: Index signature of object type implicitly has an 'any' type.
Для меня это сработало:var color: Color = (<any>Color)[green];
(протестировано с версией 1.4)