我有一个这样定义的枚举:
export enum GoalProgressMeasurements {
Percentage = 1,
Numeric_Target = 2,
Completed_Tasks = 3,
Average_Milestone_Progress = 4,
Not_Measured = 5
}
然而,我希望它被表示为一个对象数组/列表从我们的API如下:
[{id: 1, name: 'Percentage'},
{id: 2, name: 'Numeric Target'},
{id: 3, name: 'Completed Tasks'},
{id: 4, name: 'Average Milestone Progress'},
{id: 5, name: 'Not Measured'}]
是否有简单和本地的方法来做到这一点,或者我必须构建一个函数,将枚举转换为int和字符串,并将对象构建为数组?
如果你使用的是ES8
只有在这种情况下,它才会工作得很好。它会给你给定枚举的值数组。
enum Colors {
WHITE = 0,
BLACK = 1,
BLUE = 3
}
const colorValueArray = Object.values(Colors); //[ 'WHITE', 'BLACK', 'BLUE', 0, 1, 3 ]
你会得到这样的colorValueArray ['WHITE', 'BLACK', 'BLUE', 0,1,3]。所有的键都在数组的前半部分,所有的值都在数组的后半部分。
甚至这种枚举也可以正常工作
enum Operation {
READ,
WRITE,
EXECUTE
}
但是这种解决方案不适用于这样的异构枚举
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
一个棘手的地方是TypeScript会在触发对象中'double'映射enum,所以它可以通过键和值访问。
enum MyEnum {
Part1 = 0,
Part2 = 1
}
将以
{
Part1: 0,
Part2: 1,
0: 'Part1',
1: 'Part2'
}
所以你应该在映射之前先过滤对象。所以@Diullei的解决方案是正确的。这是我的实现:
// Helper
const StringIsNumber = value => isNaN(Number(value)) === false;
// Turn enum into array
function ToArray(enumme) {
return Object.keys(enumme)
.filter(StringIsNumber)
.map(key => enumme[key]);
}
像这样使用它:
export enum GoalProgressMeasurements {
Percentage,
Numeric_Target,
Completed_Tasks,
Average_Milestone_Progress,
Not_Measured
}
console.log(ToArray(GoalProgressMeasurements));
我不建议在需要枚举条目列表的情况下使用TS enum。
在运行时,Enum是作为对象实现的,但它只在这种情况下工作:
enum X {
Z = 'z',
F = 'f'
};
console.log(Object.values(X))
console.log(Object.keys(X))
>>>
[LOG]: ["z", "f"]
[LOG]: ["Z", "F"]
在这种情况下,它与陷阱一起工作(TS让你通过它的数值访问值):
enum X {
Z,
F
};
console.log(Object.values(X))
console.log(Object.keys(X))
>>>
[LOG]: ["Z", "F", 0, 1]
[LOG]: ["0", "1", "Z", "F"]
因此,根据Enum定义,任何你写在Enum上循环的函数都将工作/失败。这是…不好的。
我的结论是:Enum不是被设计用来作为对象的。如果你需要访问键和值集合,请使用const而不是enum:
const Enumed = {
X: 1,
Y: 2
}
Typescript将控制对象键的存在,你将能够使用object。钥匙等,以安全一致的方式。
我不认为顺序是可以保证的,否则就很容易切片Object的后半部分。条目的结果和映射来自那里。
上述答案的唯一(非常小的)问题是
字符串和数字之间有很多不必要的类型转换。
当一次迭代同样干净有效时,条目将迭代两次。
type StandardEnum = { [id: string]: number | string; [nu: number]: string;}
function enumToList<T extends StandardEnum> (enm: T) : { id: number; description: string }[] {
return Object.entries(enm).reduce((accum, kv) => {
if (typeof kv[1] === 'number') {
accum.push({ id: kv[1], description: kv[0] })
}
return accum
}, []) // if enum is huge, perhaps pre-allocate with new Array(entries.length / 2), however then push won't work, so tracking an index would also be required
}
你可以这样做:
export enum GoalProgressMeasurements {
Percentage = 1,
Numeric_Target = 2,
Completed_Tasks = 3,
Average_Milestone_Progress = 4,
Not_Measured = 5
}
export class GoalProgressMeasurement {
constructor(public goalProgressMeasurement: GoalProgressMeasurements, public name: string) {
}
}
export var goalProgressMeasurements: { [key: number]: GoalProgressMeasurement } = {
1: new GoalProgressMeasurement(GoalProgressMeasurements.Percentage, "Percentage"),
2: new GoalProgressMeasurement(GoalProgressMeasurements.Numeric_Target, "Numeric Target"),
3: new GoalProgressMeasurement(GoalProgressMeasurements.Completed_Tasks, "Completed Tasks"),
4: new GoalProgressMeasurement(GoalProgressMeasurements.Average_Milestone_Progress, "Average Milestone Progress"),
5: new GoalProgressMeasurement(GoalProgressMeasurements.Not_Measured, "Not Measured"),
}
你可以这样使用它:
var gpm: GoalProgressMeasurement = goalProgressMeasurements[GoalProgressMeasurements.Percentage];
var gpmName: string = gpm.name;
var myProgressId: number = 1; // the value can come out of drop down selected value or from back-end , so you can imagine the way of using
var gpm2: GoalProgressMeasurement = goalProgressMeasurements[myProgressId];
var gpmName: string = gpm.name;
您可以根据需要使用对象的附加属性扩展GoalProgressMeasurement。我将这种方法用于每个应该是包含多个值的对象的枚举。