字符串枚举的反向映射

时间:2017-07-03 10:16:59

标签: javascript node.js typescript visual-studio-code msdn

我想在typescript中使用字符串枚举,但我看不到支持反向映射。 我有这样的枚举:

enum Mode {
    Silent = "Silent",
    Normal = "Normal",
    Deleted = "Deleted"
}

我需要像这样使用它:

let modeStr: string;
let mode: Mode = Mode[modeStr];

并且我不知道modeStr字符串中的内容是什么,如果字符串未在枚举定义中显示,我需要将其解析为枚举,或者在运行时解析失败。 我怎么能尽可能整洁呢? 提前谢谢

6 个答案:

答案 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'。

https://stackblitz.com/edit/typescript-hyndj1?file=index.ts

答案 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];