获取枚举名称
如果要根据枚举动态创建对象中的所有键,则需要get the enum keys。没有内置方法可以做到这一点 - 问题是 TypeScript 在键和值之间生成双重绑定以确保两者的唯一性。
enum ArchiveStatus {
Current = 0,
Archive = 1,
}
有效地编译为:
ArchiveStatus = {
"Current": 0,
"Archive": 1,
0: "Current",
1: "Archive",
}
但是,如果枚举值都是数字,您可以使用 Object.values(ArchiveStatus).filter(x => typeof x !== "number") 将它们过滤掉,这将只留下名称:
enum ArchiveStatus {
Current = 0,
Archive = 1
}
//create a type for the names for type safety later
type ArchiveStatusName = keyof typeof ArchiveStatus;
const enumNames = Object.values(ArchiveStatus)
.filter(x => typeof x !== "number") as ArchiveStatusName[]; //type assertion needed as compiler cannot determine this is safe
Playground Link
JavaScript 演示:
const ArchiveStatus = {
"Current": 0,
"Archive": 1,
0: "Current",
1: "Archive",
}
const enumNames = Object.values(ArchiveStatus)
.filter(x => typeof x !== "number");
console.log(enumNames);
概括过滤
现在过滤器调用可以概括为使用枚举的任何名称来调用它们。这就是我们想要做的,因为我们已经有了名字。
使用柯里化函数很容易做到这一点。这是您的代码重构以使用它:
//formalised the interface for the data
interface DataItem {
name: string;
Archive_Status: ArchiveStatus;
}
//generalised filter function for each status
const statusFilter = (status: ArchiveStatus) => (item: DataItem) : boolean =>
item.Archive_Status === status;
//using the filters
const filteredData = {
Current: data.filter(statusFilter(ArchiveStatus.Current)),
Archive: data.filter(statusFilter(ArchiveStatus.Archive))
}
Playground Link
使用状态和过滤数据生成一个对象
使用上面的工具,只需将它们放在一起即可。我们可以遍历所有的enumNames 并创建一个对象
JavaScript 提供了一种方便的方法来创建对象,称为Object.fromEntries - 它采用一对数组。对于 TypeScript,它是 [key: string, value: any] 类型的元组数组。我们可以创建这样一个结构,然后将其交给Object.fromEntries 为我们生成对象:
//create key-value pairs for the dynamically created object
const pairs = enumNames.map(name => [
name,
data.filter(statusFilter(ArchiveStatus[name]))
]);
const filteredData = Object.fromEntries(pairs);
Playground Link
过滤掉没有任何数据的键
如果需要,我们可以跳过值没有数据的任何键。我们可以删除第二项是空数组的对:
//create key-value pairs for the dynamically created object
const pairs = enumNames.map(name => [
name,
data.filter(statusFilter(ArchiveStatus[name]))
])
.filter(([, value]) => value.length > 0); // remove any pair where the value is an empty array
const filteredData = Object.fromEntries(pairs);
Playground Link