我有这样的枚举,
enum Traits {
None = 0,
Friendly = 1 << 0, // 0001
Mean = 1 << 1, // 0010
Funny = 1 << 2, // 0100
Boring = 1 << 3, // 1000
All = ~(~0 << 4) // 1111
}
let traits = Traits.Mean | Traits.Funny
console.log(traits);
这个控制台将记录6
。反过来怎么办?如果我通过6。我想得到Traits.Mean , Traits.Funny
。
你可以这样做:
for (var prop in Traits) {
if(Traits[prop] & 6) {
console.log(prop);
}
}
虽然enum
的定义值的名称存在于运行时表示enum
类型的对象中,但不存在复合值。我们可以编写一个计算复合显示字符串的函数:
enum Traits {
None = 0,
Friendly = 1 << 0, // 0001
Mean = 1 << 1, // 0010
Funny = 1 << 2, // 0100
Boring = 1 << 3, // 1000
FunnyBoringCustom = Funny | Boring, // Defined compund
All = ~(~0 << 4) // 1111
}
let traits = Traits.Mean | Traits.Funny
function enumToString<T extends { [name: string]: any }>(enumType: T, enumValue: T[keyof T], separator = ','){
// Predefined value
if(enumType[enumValue]!== undefined){
return enumType[enumValue];
}
let values = Object
.getOwnPropertyNames(enumType)
// We only take numeric values, the enum contains both direct and reverse lookup
.filter(x => Number.isInteger(enumType[x]) && enumType[x] != 0)
// Sort the values, so that compound values will be before their constituents
.sort((a,b) => enumType[b] - enumType[a]);
var result = "";
for(let e of values){
if((enumValue & enumType[e]) == enumType[e] ){
result += result !== "" ? separator: "";
result+=e;
// Exclude the bits that were in this value, to treat defined compound values correcty.
enumValue = enumValue & (~enumType[e]);
}
}
return result;
}
// Usage
console.log(enumToString(Traits, traits)); // Funny,Mean
console.log(enumToString(Traits, 6)); // Funny,Mean
console.log(enumToString(Traits, Traits.Friendly | Traits.Boring)) //Boring,Friendly
console.log(enumToString(Traits, Traits.Funny | Traits.Boring)) //FunnyBoringCustom
console.log(enumToString(Traits, Traits.All)); // All
编辑
我们可以看到该函数做了大量的工作,我们可以缓存结果。
我们可以在enum
对象中做到这一点:
function enumToString<T extends { [name: string]: any }>(enumType: T, enumValue: T[keyof T], separator = ','){
...
enumType[enumValue] = result;
return result;
}
或者我们可以创建一个函数的包装版本,该函数在每个类型的不同对象中进行缓存:
function cachedEnumToString<T extends { [name: string]: any }>(enumType: T, separator = ',') {
let cache: { [name: string]: string } = {};
return function forValue(enumValue: T[keyof T]) {
var result = cache[enumValue];
if (!result) {
result = enumToString(enumType, enumValue, separator);
cache[enumValue] = result;
}
return result
}
}
// Usage
const traitsToString = cachedEnumToString(Traits);
console.log(traitsToString(traits));
console.log(traitsToString(6));
console.log(traitsToString(Traits.Friendly | Traits.Boring))
console.log(traitsToString(Traits.Funny | Traits.Boring))
console.log(traitsToString(Traits.All));