在TypeScript中转换FlaggedEnum

问题描述 投票:1回答:2

我有这样的枚举,

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

javascript angular typescript enums bitwise-operators
2个回答
1
投票

你可以这样做:

for (var prop in Traits) {
  if(Traits[prop] & 6) {
    console.log(prop);
  }
}

1
投票

虽然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));
© www.soinside.com 2019 - 2024. All rights reserved.