回答:
TypeScript 0.9の列挙型は文字列+数値ベースです。単純な変換では型アサーションは必要ありません。
enum Color{
Red, Green
}
// To String
var green: string = Color[Color.Green];
// To Enum / number
var color : Color = Color[green];
私のOSSブックには、これと他のEnumパターンに関するドキュメントがあります。https://basarat.gitbook.io/typescript/type-system/enums
var color : Color = Color[green as keyof typeof Color];
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
typedColorString = Color["Black"];
今すぐ戻るerror TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'
const color: Color = Color[colorString as keyof typeof Color];
入力文字列が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>
、次に入力する活字体は、エラーが表示されます:
インデックス式のタイプが「number」ではないため、要素は暗黙的に「any」タイプを持っています。
つまり、デフォルトでは、TypeScriptのEnum型は数値インデックスで機能しますが、
let c = Color[0]
などの文字列インデックスでは機能しませんlet c = Color["string"]
。これは、より一般的な問題であるオブジェクト文字列インデックスに対するMicrosoftチームの既知の制限です。
typeof '0'
なければなりませんstring
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
このメモは元の質問ではなく、バサラトの回答に関連しています。
自分のプロジェクトで奇妙な問題がありました。コンパイラーは、このコードと同等のコードを使用して、「文字列をColorに変換できません」とほぼ同等のエラーを出していました。
var colorId = myOtherObject.colorId; // value "Green";
var color: Color = <Color>Color[colorId]; // TSC error here: Cannot convert string to Color.
コンパイラ型の推論が混乱していることcolorId
がわかり、それは列挙値でありIDではないと考えました。問題を解決するには、IDを文字列としてキャストする必要がありました。
var colorId = <string>myOtherObject.colorId; // Force string value here
var color: Color = Color[colorId]; // Fixes lookup here.
問題の原因はわかりませんが、同じ問題が発生した場合に備えて、ここにこのメモを残しておきます。
enumに文字列値を提供する場合、ストレートキャストは問題なく機能します。
enum Color {
Green = "Green",
Red = "Red"
}
const color = "Green";
const colorEnum = color as Color;
TypeScriptコンパイラが変数のタイプが文字列であることを知っている場合、これは機能します。
let colorName : string = "Green";
let color : Color = Color[colorName];
それ以外の場合は、明示的に文字列に変換する必要があります(コンパイラの警告を回避するため)。
let colorName : any = "Green";
let color : Color = Color["" + colorName];
実行時に両方のソリューションが機能します。
<string>colorName
代わりにタイプキャストを使用しないのはなぜ"" + colorName
ですか?
この質問にはさまざまな情報が混在しているため、TypeScript を使用したモデルでの列挙型の使用に関するNickのガイドの TypeScript 2.x +の実装全体について説明します。
このガイドは、クライアント側のEnumとして便利にモデル化されるサーバーから一連の既知の文字列を取り込むクライアント側コードを作成しているユーザーを対象としています。
列挙型から始めましょう。次のようになります。
export enum IssueType {
REPS = 'REPS',
FETCH = 'FETCH',
ACTION = 'ACTION',
UNKNOWN = 'UNKNOWN',
}
ここで2つの注意点があります。
これらを文字列で裏付けられた列挙型ケースとして明示的に宣言しているため、他の無関係な数値ではなく、文字列でインスタンス化できます。
サーバーモデルに存在するオプションと存在しないオプションを追加しました:UNKNOWN
。これはundefined
好みに応じて処理できますが、| undefined
処理を簡略化するために、可能な場合は型を避けたいと思います。
UNKNOWN
ケースがあることの素晴らしい点は、コードでそれを本当に明確にして、不明な列挙型のケースのスタイルを真っ赤に点滅させて、何かを正しく処理していないことがわかるということです。
別のモデルに埋め込まれたこの列挙型を使用するか、すべてを単独で使用する可能性がありますが、JSONまたはXML(ha)から文字列型の列挙型を解析して、厳密に型指定された対応するものにする必要があります。別のモデルに埋め込まれた場合、このパーサーはクラスコンストラクターに存在します。
parseIssueType(typeString: string): IssueType {
const type = IssueType[typeString];
if (type === undefined) {
return IssueType.UNKNOWN;
}
return type;
}
enumが適切に解析されると、最終的に適切な型になります。それ以外の場合は、それを受け取り、undefined
傍受してUNKNOWN
ケースを返すことができます。undefined
不明なケースとして使用したい場合は、試行された列挙型解析の結果を返すことができます。
そこからは、解析関数を使用し、新しく強く型付けされた変数を使用するだけです。
const strongIssueType: IssueType = parseIssueType('ACTION');
// IssueType.ACTION
const wrongIssueType: IssueType = parseIssueType('UNEXPECTED');
// IssueType.UNKNOWN
IssueType.UNKNOWN
にはキーがないため、常に戻りreps
ます。文字列にハイフンが含まれているため、キーとして使用できないため、問題が解決しませんでした。
私はenum
からを得ることができる答えを探していましたstring
が、私の場合、列挙値には対応する異なる文字列値がありました。OPにはの単純な列挙型が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]];
filter
クライアントがenumからの有効な文字列を渡していると仮定すると、。そうでない場合は、undefined
返されます。enumObj
します。any
enumObj
unknown
const cantTellStr = "Can't tell";
const cantTellEnumValue = stringToEnumValue<typeof Gender, Gender>(Gender, cantTellStr);
console.log(cantTellEnumValue); // Can't tell
注:そして、誰かがコメントで指摘したように、私は noImplicitAny
。
キャストなしany
、適切なタイピング。
export const stringToEnumValue = <T, K extends keyof T>(enumObj: T, value: string): T[keyof T] | undefined =>
enumObj[Object.keys(enumObj).filter((k) => enumObj[k as K].toString() === value)[0] as keyof typeof enumObj];
また、更新されたバージョンはそれを呼び出す簡単な方法があり、より読みやすくなっています。
stringToEnumValue(Gender, "Can't tell");
列挙型の値をループする方法を知る必要があり(いくつかの列挙型の多くの順列をテストしていた)、これがうまくいくことがわかりました。
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
}
ソース:https : //blog.mikeski.net/development/javascript/typescript-enums-to-from-string/
each
1つのメソッドですべての列挙型のケースをテストします
列挙型
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;
}
}
return enumType[property];
、列挙型アイテムが次のようになっている場合はケースに入れるべきですSkills = "anyvalue"
作成した列挙型は、フォワードマッピング(name -> value)
とリバース(value -> name)
マッピングの両方を格納するオブジェクトにコンパイルされます。このクロムdevtoolsスクリーンショットから観察できるように:
デュアルマッピングの仕組みと、あるマッピングから別のキャストにキャストする方法の例を次に示します。
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
他のバリエーションは
const green= "Green";
const color : Color = Color[green] as Color;
--noImplicitAny
(VSではチェックされていない「暗黙の 'any'タイプを許可する」)。それはerror TS7017: Index signature of object type implicitly has an 'any' type.
私にとってこれは機能しました:(var color: Color = (<any>Color)[green];
バージョン1.4でテスト済み)