字符串枚举的反向映射
Reverse-Mapping for String Enums
我想在打字稿中使用字符串枚举,但我看不到它支持反向映射。
我有一个这样的枚举:
enum Mode {
Silent = "Silent",
Normal = "Normal",
Deleted = "Deleted"
}
我需要这样使用它:
let modeStr: string;
let mode: Mode = Mode[modeStr];
是的,我不知道 modeStr
字符串中有什么,我需要将其解析为枚举,或者如果枚举定义中未显示该字符串,则在运行时解析失败。
我怎样才能做到尽可能整洁?
提前致谢
我们可以让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
字符串枚举为 :
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
如果您可以使用代理,我制作了一个更通用和紧凑的版本:
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>();
到目前为止我发现的最干净的方法是制作辅助地图:
let reverseMode = new Map<string, Mode>();
Object.keys(Mode).forEach((mode: Mode) => {
const modeValue: string = Mode[<any>mode];
reverseMode.set(modeValue, mode);
});
这样你就可以let mode: Mode = reverseMode.get('Silent');
优点:无需重复值,提供枚举枚举的方法,让 TSLint 开心...
编辑:我最初写 Mode[mode]
但后来 TS 可能会在这一行抛出错误 TS7015,所以我添加了强制转换。
None 的答案确实对我有用,所以我必须恢复正常才能进行循环。
我的枚举是
enum SOME_CONST{
STRING1='value1',
STRING2 ='value2',
.....and so on
}
getKeyFromValue =(value:string)=> Object.entries(SOME_CONST).filter((item)=>item[1]===value)[0][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 提供的原始对象的键和值是相同的。
对于仍在为此苦苦挣扎的所有人来说,这是完成此任务的一种快速而肮脏的方法。
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' 的模式。您零保证一旦查找完成,它不会 return 'Ignore' 超过 'Silent'。
标准类型实现此功能 - 只需检查未定义并处理。
type Mode = "Silent" | "Normal" | "Deleted";
const a = Mode["something else"];
//a will be undefined
此外,您可以在上面添加记录类型以扩展“枚举”,比如将一个简短的枚举键转换为更详细的输出(https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type):
const VerboseMode: Record<Mode, string> = {
Silent: "Silent mode",
Normal: "Normal mode",
Deleted: "This thing has been deleted"
}
我想在打字稿中使用字符串枚举,但我看不到它支持反向映射。 我有一个这样的枚举:
enum Mode {
Silent = "Silent",
Normal = "Normal",
Deleted = "Deleted"
}
我需要这样使用它:
let modeStr: string;
let mode: Mode = Mode[modeStr];
是的,我不知道 modeStr
字符串中有什么,我需要将其解析为枚举,或者如果枚举定义中未显示该字符串,则在运行时解析失败。
我怎样才能做到尽可能整洁?
提前致谢
我们可以让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
字符串枚举为
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
如果您可以使用代理,我制作了一个更通用和紧凑的版本:
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>();
到目前为止我发现的最干净的方法是制作辅助地图:
let reverseMode = new Map<string, Mode>();
Object.keys(Mode).forEach((mode: Mode) => {
const modeValue: string = Mode[<any>mode];
reverseMode.set(modeValue, mode);
});
这样你就可以let mode: Mode = reverseMode.get('Silent');
优点:无需重复值,提供枚举枚举的方法,让 TSLint 开心...
编辑:我最初写 Mode[mode]
但后来 TS 可能会在这一行抛出错误 TS7015,所以我添加了强制转换。
None 的答案确实对我有用,所以我必须恢复正常才能进行循环。 我的枚举是
enum SOME_CONST{
STRING1='value1',
STRING2 ='value2',
.....and so on
}
getKeyFromValue =(value:string)=> Object.entries(SOME_CONST).filter((item)=>item[1]===value)[0][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 提供的原始对象的键和值是相同的。
对于仍在为此苦苦挣扎的所有人来说,这是完成此任务的一种快速而肮脏的方法。
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' 的模式。您零保证一旦查找完成,它不会 return 'Ignore' 超过 'Silent'。
标准类型实现此功能 - 只需检查未定义并处理。
type Mode = "Silent" | "Normal" | "Deleted";
const a = Mode["something else"];
//a will be undefined
此外,您可以在上面添加记录类型以扩展“枚举”,比如将一个简短的枚举键转换为更详细的输出(https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type):
const VerboseMode: Record<Mode, string> = {
Silent: "Silent mode",
Normal: "Normal mode",
Deleted: "This thing has been deleted"
}