[英]TypeScript enum to object array
我有一個這樣定義的枚舉:
export enum GoalProgressMeasurements {
Percentage = 1,
Numeric_Target = 2,
Completed_Tasks = 3,
Average_Milestone_Progress = 4,
Not_Measured = 5
}
但是,我希望將它表示為我們的 API 中的 object 數組/列表,如下所示:
[{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'}]
是否有簡單的本機方法來執行此操作,或者我是否必須構建一個 function 將枚舉同時轉換為 int 和字符串,並將對象構建到數組中?
一個棘手的問題是 TypeScript 將“雙倍”映射發出的對象中的枚舉,因此可以通過鍵和值訪問它。
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));
如果您使用的是 ES8
對於這種情況,它只會工作得很好。 它將為您提供給定enum 的值數組。
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",
}
枚舉是在運行時存在的真實對象。 因此,您可以執行以下操作來反轉映射:
let value = GoalProgressMeasurements.Not_Measured;
console.log(GoalProgressMeasurements[value]);
// => Not_Measured
基於此,您可以使用以下代碼:
export enum GoalProgressMeasurements {
Percentage = 1,
Numeric_Target = 2,
Completed_Tasks = 3,
Average_Milestone_Progress = 4,
Not_Measured = 5
}
let map: {id: number; name: string}[] = [];
for(var n in GoalProgressMeasurements) {
if (typeof GoalProgressMeasurements[n] === 'number') {
map.push({id: <any>GoalProgressMeasurements[n], name: n});
}
}
console.log(map);
參考: https : //www.typescriptlang.org/docs/handbook/enums.html
簡單地說,這將返回一個枚舉值數組:
Object.values(myEnum);
簡單的解決方案。 您可以使用以下函數將 Enum 轉換為對象數組。
buildGoalProgressMeasurementsArray(): Object[] {
return Object.keys(GoalProgressMeasurements)
.map(key => ({ id: GoalProgressMeasurements[key], name: key }))
}
如果你需要去掉下划線,我們可以使用正則表達式如下:
buildGoalProgressMeasurementsArray(): Object[] {
return Object.keys(GoalProgressMeasurements)
.map(key => ({ id: GoalProgressMeasurements[key], name: key.replace(/_/g, ' ') }))
}
我用
Object.entries(GoalProgressMeasurement).filter(e => !isNaN(e[0]as any)).map(e => ({ name: e[1], id: e[0] }));
一個簡單的 1 行就可以完成這項工作。
它通過 3 個簡單的步驟完成工作
- 使用Object.entries
加載鍵和值的組合。
- 過濾掉非數字(因為打字稿生成反向查找的值)。
- 然后我們將它映射到我們喜歡的數組對象。
class EnumHelpers {
static getNamesAndValues<T extends number>(e: any) {
return EnumHelpers.getNames(e).map(n => ({ name: n, value: e[n] as T }));
}
static getNames(e: any) {
return EnumHelpers.getObjValues(e).filter(v => typeof v === 'string') as string[];
}
static getValues<T extends number>(e: any) {
return EnumHelpers.getObjValues(e).filter(v => typeof v === 'number') as T[];
}
static getSelectList<T extends number, U>(e: any, stringConverter: (arg: U) => string) {
const selectList = new Map<T, string>();
this.getValues(e).forEach(val => selectList.set(val as T, stringConverter(val as unknown as U)));
return selectList;
}
static getSelectListAsArray<T extends number, U>(e: any, stringConverter: (arg: U) => string) {
return Array.from(this.getSelectList(e, stringConverter), value => ({ value: value[0] as T, presentation: value[1] }));
}
private static getObjValues(e: any): (number | string)[] {
return Object.keys(e).map(k => e[k]);
}
}
感謝polkovnikov.ph,我終於找到了適用於大多數用例的解決方案。
type Descripted<T> = {
[K in keyof T]: {
readonly id: T[K];
readonly description: string;
}
}[keyof T]
/**
* Helper to produce an array of enum descriptors.
* @param enumeration Enumeration object.
* @param separatorRegex Regex that would catch the separator in your enum key.
*/
export function enumToDescriptedArray<T>(enumeration: T, separatorRegex: RegExp = /_/g): Descripted<T>[] {
return (Object.keys(enumeration) as Array<keyof T>)
.filter(key => isNaN(Number(key)))
.filter(key => typeof enumeration[key] === "number" || typeof enumeration[key] === "string")
.map(key => ({
id: enumeration[key],
description: String(key).replace(separatorRegex, ' '),
}));
}
例子:
export enum GoalProgressMeasurements {
Percentage = 1,
Numeric_Target = 2,
Completed_Tasks = 3,
Average_Milestone_Progress = 4,
Not_Measured = 5
}
console.log(enumToDescriptedArray(GoalProgressMeasurements))
// Produces:
/*
[
{id: 1, description: "Percentage"},
{id: 2, description: "Numeric Target"},
{id: 3, description: "Completed Tasks"},
{id: 4, description: "Average Milestone Progress"},
{id: 5, description: "Not Measured"}
]
*/
此外,我使用一個有用的 util 函數將枚舉對象映射到它具有的可用值數組:
type NonFunctional<T> = T extends Function ? never : T;
/**
* Helper to produce an array of enum values.
* @param enumeration Enumeration object.
*/
export function enumToArray<T>(enumeration: T): NonFunctional<T[keyof T]>[] {
return Object.keys(enumeration)
.filter(key => isNaN(Number(key)))
.map(key => enumeration[key])
.filter(val => typeof val === "number" || typeof val === "string");
}
enum Colors1 {
WHITE = 0,
BLACK = 1
}
console.log(Object.values(Colors1)); // ['WHITE', 'BLACK', 0, 1]
console.log(enumToArray(Colors1)); // [0, 1]
enum Colors2 {
WHITE = "white",
BLACK = "black"
}
console.log(Object.values(Colors2)); // ['white', 'black']
console.log(enumToArray(Colors2)); // ['white', 'black']
enum Colors4 {
WHITE = "white",
BLACK = 0
}
console.log(Object.values(Colors4)); // ["BLACK", "white", 0]
console.log(enumToArray(Colors4)); // ["white", 0]
enum Colors3 {
WHITE = "white",
BLACK = "black"
}
namespace Colors3 {
export function fun() {}
}
console.log(Object.values(Colors3)); // ['white', 'black', Function]
console.log(enumToArray(Colors3)); // ['white', 'black']
我不喜歡上述任何一個答案,因為它們都沒有正確處理可以是 TypeScript 枚舉中的值的字符串/數字的混合。
以下函數遵循 TypeScript 枚舉的語義,以提供適當的鍵值映射。 從那里,獲取對象數組或僅鍵或僅值是微不足道的。
/**
* Converts the given enum to a map of the keys to the values.
* @param enumeration The enum to convert to a map.
*/
function enumToMap(enumeration: any): Map<string, string | number> {
const map = new Map<string, string | number>();
for (let key in enumeration) {
//TypeScript does not allow enum keys to be numeric
if (!isNaN(Number(key))) continue;
const val = enumeration[key] as string | number;
//TypeScript does not allow enum value to be null or undefined
if (val !== undefined && val !== null)
map.set(key, val);
}
return map;
}
示例用法:
enum Dog {
Rover = 1,
Lassie = "Collie",
Fido = 3,
Cody = "Mutt",
}
let map = enumToMap(Dog); //Map of keys to values
let objs = Array.from(map.entries()).map(m => ({id: m[1], name: m[0]})); //Objects as asked for in OP
let entries = Array.from(map.entries()); //Array of each entry
let keys = Array.from(map.keys()); //An array of keys
let values = Array.from(map.values()); //An array of values
我還要指出,OP 正在向后考慮枚舉。 枚舉中的“鍵”在技術上位於左側,而值位於右側。 TypeScript 允許您根據需要重復 RHS 上的值。
首先,我們獲得此枚舉的鍵數組。 然后,使用 map() 函數,我們將數據轉換為所需的格式。 id 是從key 中獲取的,name 是通過相同的key 從enum 中獲取的。
const converted = Object.keys(GoalProgressMeasurements).map(key => {
return {
id: GoalProgressMeasurements[key],
name: key,
};
});
enum GoalProgressMeasurements { Percentage = 1, Numeric_Target = 2, Completed_Tasks = 3, Average_Milestone_Progress = 4, Not_Measured = 5 } const array = [] for (const [key, value] of Object.entries(GoalProgressMeasurements)) { if (!Number.isNaN(Number(key))) { continue; } array.push({ id: value, name: key.replace('_', '') }); } console.log(array);
在需要枚舉條目列表的情況下,我不鼓勵使用 TS 枚舉。
在運行時枚舉被實現為 object,但它僅在這種情況下按預期工作:
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"]
因此,根據枚舉定義,您編寫的任何 function 都將在枚舉上循環工作/失敗。 這是...不好。
我的結論:Enum 並非設計為用作 object。如果您需要訪問鍵和值 collections,請使用const
而不是enum
:
const Enumed = {
X: 1,
Y: 2
}
Typescript 將控制 object 密鑰的存在,您將能夠以安全一致的方式執行Object.keys
等操作。
export function enumKeys(E: any): string[] {
return Object.keys(E).filter(k => isNaN(Number(k)));
}
export function enumValues(E: any): string[] | number[] {
return enumKeys(E).map(k => E[k as any]);
}
適用於:
enum TestA {
RED = "red",
BLUE = "blue"
}
enum TestB {
ONE = 1,
TWO = 2
}
有一個簡單的解決方案,所以當你運行Object.keys(Enum)
,它會給你一個值和鍵的數組,在第一個切片值和第二個鍵中,那么為什么我們不只返回第二個切片,下面的這段代碼對我有用。
enum Enum {
ONE,
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN
}
const keys = Object.keys(Enum);
console.log(keys.slice(keys.length / 2));
function enumKeys(_enum) {
const entries = Object.entries(_enum).filter(e => !isNaN(Number(e[0])));
if (!entries.length) {
// enum has string values so we can use Object.keys
return Object.keys(_enum);
}
return entries.map(e => e[1]);
}
TS:
僅適用於短(<10 個元素)枚舉
const keys = Object.keys(Enum).filter((el: string) => el.length > 1)
console.log(keys)
export enum Weeks {
MONDAY = 1,
TUESDAY= 2,
WEDNESDAY = 3,
THURSDAY = 4,
FRIDAY = 5,
SATURDAY=6,
SUNDAY=7,
}
function convertEnumToArray(){
const arrayObjects = []
// Retrieve key and values using Object.entries() method.
for (const [propertyKey, propertyValue] of Object.entries(Weeks)) {
// Ignore keys that are not numbers
if (!Number.isNaN(Number(propertyKey))) {
continue;
}
// Add keys and values to array
arrayObjects.push({ id: propertyValue, name: propertyKey });
}
console.log(arrayObjects);
}
將產生以下內容:
[
{ id: 1, name: 'MONDAY' },
{ id: 2, name: 'TUESDAY' },
{ id: 3, name: 'WEDNESDAY' },
{ id: 4, name: 'THURSDAY' },
{ id: 5, name: 'FRIDAY' },
{ id: 6, name: 'SATURDAY' },
{ id: 7, name: 'SUNDAY' }
]
無恥地從這個博客竊取
我從幾個月就知道打字稿,下面的解決方案對我有用。 希望它也可以幫助某人-
export enum ScheduleType {
Basic = <any>'B',
Consolidated = <any>'C',
}
scheduleTypes = Object.keys(ScheduleType)
.filter((k, i) => i % 2)
.map((key: any) => {
return {
systemValue: key,
displayValue: ScheduleType[key],
};
});
它給出了以下結果 - [{displayValue: "Basic", systemValue: "B"}, {displayValue: "Consolidated", systemValue: "C"}]
你可以這樣做:
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。 對於應該是包含多個值的對象的每個枚舉,我都使用這種方法。
由於具有字符串值的枚舉不同於具有數字值的枚舉,因此最好從 @user8363 解決方案中過濾非數字。
以下是如何從枚舉字符串或混合數字中獲取值的方法:
//Helper export const StringIsNotNumber = value => isNaN(Number(value)) === true; // Turn enum into array export function enumToArray(enumme) { return Object.keys(enumme) .filter(StringIsNotNumber) .map(key => enumme[key]); }
我在 TypeScript 線程中感到驚訝,沒有人提供支持鍵入的有效 TypeScript 函數。 這是@user8363 解決方案的變體:
const isStringNumber = (value: string) => isNaN(Number(value)) === false;
function enumToArray<T extends {}>(givenEnum: T) {
return (Object.keys(givenEnum).filter(isStringNumber) as (keyof T)[]).map(
(key) => givenEnum[key]
);
}
我不認為可以保證順序,否則很容易將Object.entries
結果的后半部分切片並從那里映射。
上述答案的唯一(非常小的)問題是
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 DocumentationTypeEnum {
GDPR = 'GDPR',
HELP = 'HELP',
OTHER = 'OTHER',
FOOTER = 'FOOTER'
}
const keys = Object.keys(DocumentationTypeEnum);
console.log(keys); // Output : ["GDPR", "HELP", "OTHER", "FOOTER"]
export const isNumber = (num?: Value | null): num is number => {
if (num === undefined || num === null) {
return false;
}
const number = +num;
if (number - number !== 0) {
// Discard Infinity and NaN
return false;
}
if (number === num) {
return true;
}
if (typeof num === 'string') {
return !(number === 0 && num.trim() === '');
}
return false;
};
enum En {
ewq1 = 1,
we2 = 'ss',
sad = 'sad',
}
type TEnum = {
[id: string]: number | string;
[nu: number]: string;
}
export const getEnumValues = <T extends TEnum>(enumerable: T) =>
Object.keys(enumerable)
.filter((x) => !isNumber(x))
.map((key) => enumerable[key]) as Array<T[keyof T]>
console.log(getEnumValues(En)) // [1, "ss", "sad"]
另一種方式是
export const GoalNames = {
[GoalProgressMeasurements.Percentage] = 'Percentage',
[GoalProgressMeasurements.Numeric_Target] = 'Numeric Target',
[GoalProgressMeasurements.Completed_Tasks] = 'Completed Tasks',
[GoalProgressMeasurements.Average_Milestone_Progress] = 'Average Milestone Progress',
[GoalProgressMeasurements.Not_Measured] = 'Not Measured'
}
你可以打電話:
const name = GoalNames[goalEnumVal];
我是這樣解決的
const listKeys = Object.keys(TripStatus); //TripStatus is enum type
const numOfItem = listKeys.length/2;
for(let i=0; i<numOfItem; i++){
this.listStatus.push({
id: listKeys[i],
name: listKeys[numOfItem+i]
})
}
只有一行:
Object.entries(GoalProgressMeasurements).map(([key, value]) => ({id: key, value: value}))
讓枚舉變量為:
enum EnumName {
A = 1,
B = 2
};
然后列表是:
const list = Object.keys(Enum)
.filter((value => isNaN(Number(value)) === false))
.map(key => ({ id: key, value: Enum[key] }));
列表的值將是
list = [
{ id:1 , value: A },
{ id:2 , value: B },
];
this worked for me :
export enum FeedBackType {
FEEDBACK1= 'FEEDBACK1',
FEEDBACK2= 'FEEDBACK2',
FEEDBACK3= 'FEEDBACK3',
}
-----------------------------------------------------------------
export function getTypeFeedBackList() {
let feedbackList: FeedBackType[] = [];
Object.keys(FeedBackType).map((key) => {
let strEnum = key as unknown as FeedBackType;
feedbackList.push(strEnum);
});
return feedbackList;
}
----------------------------------------------------------------
declare this :
public feedbackList: FeedBackType[] = [];
and after call your function in :
ngOnInit(): void {
this.feedbackList = getTypeFeedBackList();
console.log(this.feedbackList);
}
Happy coding ;)
我已經解決了它,這樣。 假設你有一個像下面這樣的枚舉
export enum UnitEnum {
GRAM = 'gm',
KILOGRAM = 'kg',
LITRE = 'lt',
CENTIMETER = 'cm',
INCH = 'in',
METER = 'mt',
KILOMETER = 'km',
}
而且,你有一個像這樣的 class,
export interface Unit {
Name: string;
Symbol: string;
}
然后你可以創建一個如下所示的 function 到 map 異構枚舉到某種類型的 object,
export function getDefaultUnits() {
const myUnits = Object.entries(UnitEnum).map(x => {
return { Name: x[0], Symbol: x[1] } as Unit
})
console.log(myUnits);
return myUnits;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.