如何从 TypeScript 中的数字获取所有枚举标志?

How to get all Enum Flags from a Number in TypeScript?

鉴于:
枚举:{1, 4, 16}
标志:20

时间: 我将标志传递给函数

然后: 我得到给定枚举的标志数组:[4, 16]

注意:我尝试手动将 Enum 转换为数组并将值视为数字。但是当涉及到 TS 时我不知所措,我想使该函数动态化以防 Enum 发生变化。我真的不想硬编码。请帮忙!

enum Enum {
    one = 1,
    four = 4,
    sixteen = 16,
}

const Flags: number = 20;

function getEnumValues(flags: number): Enum[] {
    const enumFlags = [1, 4, 16];
    
    const enums: Enum[] = [];

    enumFlags.forEach(ef => {
        if ((ef & flags) != 0) {
            enums.push(ef);
        }
    })

    return enums;
}

console.log(getEnumValues(Flags));

在此处找到解决方案: 不好,因为我的 Enum 不是序列 2 并且缺少 8。

如果您担心在函数的 enumFlags 数组中重复 Enum 值,您可以动态获取它们:

const enumFlags = Object.values(Enum)
    .filter((value): value is number => typeof value === "number");

您需要将 filter 回调设为类型保护函数(使用 type predicatevalue is number),否则 TypeScript 认为数组的类型为 (string | Enum)[]。但我们知道它不是,因为我们正在做 typeof === "number".

Playground link

由于构建该数组不是免费的,因此可能值得在 Enum 定义之后进行一次,然后重新使用它。也就是说,虽然它不是免费的,但它确实很便宜(并且保持它也不是免费的:它占用 [一点点] 内存)。

我过去也遇到过类似的挑战。巧合的是,我写了一篇关于这个的文章,因为这是一个非常有趣的挑战。

您可以在此处找到 link:https://dev.to/sincovschi/bitwise-enum-flags-to-generate-html-from-array-3576

您首先需要的是一个帮助程序,它通过将 TS enum 视为普通对象来将 Enum 的标志提取为数组。之后,您的方法可以通过遍历标志并查看它是否存在于您的号码中来实现。

从上述 link 代码沙箱复制的代码段。

const isPowerOfTwo = (x: number): boolean => {
  return x != 0 && (x & (x - 1)) == 0;
};

export function getEnumFlags<
  O extends object,
  K extends O[keyof O] = O[keyof O]
>(obj: O): K[] {
  const isFlag = (arg: string | number | K): arg is K => {
    const nArg = Number(arg);
    const isNumber = !Number.isNaN(nArg);
    return isNumber && isPowerOfTwo(nArg);
  };

  const enumFlags: K[] = [];

  Object.keys(obj).forEach(key => {
    const nKey = Number(key);
    if (isFlag(nKey)) {
      enumFlags.push(nKey);
    }
  });

  return enumFlags;
}