如何从 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 predicate、value is number
),否则 TypeScript 认为数组的类型为 (string | Enum)[]
。但我们知道它不是,因为我们正在做 typeof === "number"
.
由于构建该数组不是免费的,因此可能值得在 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;
}
鉴于:
枚举:{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));
在此处找到解决方案:
如果您担心在函数的 enumFlags
数组中重复 Enum
值,您可以动态获取它们:
const enumFlags = Object.values(Enum)
.filter((value): value is number => typeof value === "number");
您需要将 filter
回调设为类型保护函数(使用 type predicate、value is number
),否则 TypeScript 认为数组的类型为 (string | Enum)[]
。但我们知道它不是,因为我们正在做 typeof === "number"
.
由于构建该数组不是免费的,因此可能值得在 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;
}