web-dev-qa-db-ja.com

TypeScript列挙型からオブジェクト配列

このように定義された列挙型があります:

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と文字列の両方にキャストし、オブジェクトを配列に構築する関数を構築する必要がありますか?

33
AnimaSola

列挙型は、実行時に存在する実際のオブジェクトです。そのため、次のような方法でマッピングを逆にすることができます。

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

19
Diullei

トリッキーなビットは、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));
17
user8363

簡単なソリューション。次の関数を使用して、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, ' ') }))
 }
8
Manoj Shrestha
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]);
    }
}
4
Liam Kernighan

ES6を使用している場合

与えられたenumの値配列を提供します。

enum colors = {
  "WHITE" : 0,
  "BLACK" : 1
}

const colorValueArray = Object.values(colors);
3
Jai Prak

これは次の方法で実行できます。

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を拡張できます。値を超えるオブジェクトを含むすべての列挙に対してこのアプローチを使用しています。

0