我想在typescript中使用字符串枚举,但我看不到支持反向映射。 我有这样的枚举:
enum Mode {
Silent = "Silent",
Normal = "Normal",
Deleted = "Deleted"
}
我需要像这样使用它:
let modeStr: string;
let mode: Mode = Mode[modeStr];
并且我不知道modeStr
字符串中的内容是什么,如果字符串未在枚举定义中显示,我需要将其解析为枚举,或者在运行时解析失败。
我怎么能尽可能整洁呢?
提前谢谢
答案 0 :(得分:13)
我们可以使Mode
成为同一类型的类型和值。
type Mode = string;
let Mode = {
Silent: "Silent",
Normal: "Normal",
Deleted: "Deleted"
}
let modeStr: string = "Silent";
let mode: Mode;
mode = Mode[modeStr]; // Silent
mode = Mode.Normal; // Normal
mode = "Deleted"; // Deleted
mode = Mode["unknown"]; // undefined
mode = "invalid"; // "invalid"
更严格的版本:
type Mode = "Silent" | "Normal" | "Deleted";
const Mode = {
get Silent(): Mode { return "Silent"; },
get Normal(): Mode { return "Normal"; },
get Deleted(): Mode { return "Deleted"; }
}
let modeStr: string = "Silent";
let mode: Mode;
mode = Mode[modeStr]; // Silent
mode = Mode.Normal; // Normal
mode = "Deleted"; // Deleted
mode = Mode["unknown"]; // undefined
//mode = "invalid"; // Error
字符串枚举为this answer:
enum Mode {
Silent = <any>"Silent",
Normal = <any>"Normal",
Deleted = <any>"Deleted"
}
let modeStr: string = "Silent";
let mode: Mode;
mode = Mode[modeStr]; // Silent
mode = Mode.Normal; // Normal
//mode = "Deleted"; // Error
mode = Mode["unknown"]; // undefined
答案 1 :(得分:3)
如果您对使用Proxies感到满意,我会制作一个更通用的&amp;紧凑版:
stringEnum.ts
export type StringEnum<T extends string> = {[K in T]: K}
const proxy = new Proxy({}, {
get(target, property) {
return property;
}
})
export default function stringEnum<T extends string>(): StringEnum<T> {
return proxy as StringEnum<T>;
}
用法:
import stringEnum from './stringEnum';
type Mode = "Silent" | "Normal" | "Deleted";
const Mode = stringEnum<Mode>();
答案 2 :(得分:3)
到目前为止,我发现的最简洁的方法是制作二级地图:
using System.IO;
...
string dir = Path.GetDirectoryName("/:\\test\\temp.txt");
// .net 4.6.1: throws ArgumentException: The path is not of a legal form.
// .net 4.6.2 and above: dir = \:\test
因此你可以let reverseMode = new Map<string, Mode>();
Object.keys(Mode).forEach((mode: Mode) => {
const modeValue: string = Mode[<any>mode];
reverseMode.set(modeValue, mode);
});
优点:无需重复值,提供枚举枚举的方法,让TSLint保持高兴......
编辑:我最初写let mode: Mode = reverseMode.get('Silent');
但是TS可能会在这一行抛出错误TS7015,所以我添加了演员。
答案 3 :(得分:0)
此答案来自@PhiLho,
我没有足够的代表来评论他的信息。
let reverseMode = new Map<string, Mode>();
Object.keys(Mode).forEach((mode: Mode) => {
const modeValue: string = Mode[<any>mode];
reverseMode.set(modeValue, mode);
});
但是,.set
的第一个参数应该是键,第二个参数应该是值。
reverseMode.set(modeValue, mode);
应该是...
reverseMode.set(mode, modeValue);
导致此...
let reverseMode = new Map<string, ErrorMessage>();
Object.keys(ErrorMessage).forEach((mode: ErrorMessage) => {
const modeValue: string = ErrorMessage[<any>mode];
reverseMode.set(mode, modeValue);
});
@PhiLho可能会错过它的原因是因为OP提供的原始对象的键和值相同。
答案 4 :(得分:0)
对于仍在为此苦苦挣扎的所有人来说,这是一种快速而肮脏的方式来完成这项工作。
enum Mode {
Silent = "Silent",
Normal = "Normal",
Deleted = "Deleted"
}
const currMode = 'Silent',
modeKey = Object.keys(Mode)[(Object.values(Mode) as string[]).indexOf(currMode)];
但是,您应该注意一些注意事项!
Microsoft 将 Git 错误标记为“按预期工作”的最可能原因可能是因为这涉及字符串文字,因为枚举最初被设计为可索引的。虽然上面的代码可以和 TSLint 一起工作,但它有两个问题。对象在转换为数组时不能保证保留预期的顺序,我们正在处理可能唯一也可能不唯一的字符串文字。
看看这个 StackBlitz,其中有两个值为“Silent”的模式。您有零保证,一旦查找完成,它不会返回 'Ignore' 而不是 'Silent'。
答案 5 :(得分:-1)
没有一个答案对我真正有用,因此我必须回到正常状态。 我的枚举是
enum SOME_CONST{
STRING1='value1',
STRING2 ='value2',
.....and so on
}
getKeyFromValue =(value:string)=> Object.entries(SOME_CONST).filter((item)=>item[1]===value)[0][0];