program story

열거 형 유형을 프로그래밍 방식으로 열거하는 방법은 무엇입니까?

inputbox 2020. 10. 11. 10:33
반응형

열거 형 유형을 프로그래밍 방식으로 열거하는 방법은 무엇입니까?


내가 타이프을 말해봐 enum, MyEnum등 다음과 같습니다 :

enum MyEnum {
    First,
    Second,
    Third
}

TypeScript 0.9.5에서 enum배열을 생성하는 가장 좋은 방법은 무엇입니까 ? 예:

var choices: MyEnum[]; // or Array<MyEnum>
choices = MyEnum.GetValues(); // plans for this?
choices = EnumEx.GetValues(MyEnum); // or, how to roll my own?

다음은 해당 열거 형의 JavaScript 출력입니다.

var MyEnum;
(function (MyEnum) {
    MyEnum[MyEnum["First"] = 0] = "First";
    MyEnum[MyEnum["Second"] = 1] = "Second";
    MyEnum[MyEnum["Third"] = 2] = "Third";
})(MyEnum || (MyEnum = {}));

다음과 같은 객체입니다.

Object {
    0: "First",
    1: "Second",
    2: "Third",
    First: 0,
    Second: 1,
    Third: 2
}

회원 이름

열거 형 멤버 이름을 얻으려면 해당 값이 숫자 일 때 개체의 키를 필터링 할 수 있습니다. 이렇게하면 동일한 값을 가진 이름을 찾을 수 있습니다.

const names = Object.keys(MyEnum)
    .filter(k => typeof MyEnum[k] === "number") as string[];

포함 : ["First", "Second", "Third"]

멤버 값

열거 형 멤버 값을 가져 오는 동안 개체 값을 숫자로 필터링 할 수 있습니다.

const values = Object.keys(MyEnum)
    .map(k => MyEnum[k])
    .filter(v => typeof v === "number") as number[];

포함 : [0, 1, 2]

확장 클래스

이를 수행하는 가장 좋은 방법은 자신의 함수 (예 :)를 만드는 것 EnumEx.getNames(MyEnum)입니다. 열거 형에 함수를 추가 할 수 없습니다.

class EnumEx {
    private constructor() {
    }

    static getNamesAndValues<T extends number>(e: any) {
        return EnumEx.getNames(e).map(n => ({ name: n, value: e[n] as T }));
    }

    static getNames(e: any) {
        return Object.keys(e).filter(k => typeof e[k] === "number") as string[];
    }

    static getValues<T extends number>(e: any) {
        return Object.keys(e)
            .map(k => e[k])
            .filter(v => typeof v === "number") as T[];
    }
}

타이프 라이터> = 2.4 당신이 문자열 열거 형을 정의 할 수 있습니다 :

enum Color {
  RED = 'Red',
  ORANGE = 'Orange',
  YELLOW = 'Yellow',
  GREEN = 'Green',
  BLUE = 'Blue',
  INDIGO = 'Indigo',
  VIOLET = 'Violet'
}

JavaScript ES5 출력 :

var Color;
(function (Color) {
    Color["RED"] = "Red";
    Color["ORANGE"] = "Orange";
    Color["YELLOW"] = "Yellow";
    Color["GREEN"] = "Green";
    Color["BLUE"] = "Blue";
    Color["INDIGO"] = "Indigo";
    Color["VIOLET"] = "Violet";
})(Color || (Color = {}));

다음과 같은 객체입니다.

const Color = {
  "RED": "Red",
  "ORANGE": "Orange",
  "YELLOW": "Yellow",
  "GREEN": "Green",
  "BLUE": "Blue",
  "INDIGO": "Indigo",
  "VIOLET": "Violet"
}

따라서, 문자열 열거, 필터 가지 필요의 경우 Object.keys(Color)Object.values(Color)(*) 충분합니다 :

const colorKeys = Object.keys(Color);
console.log('colorKeys =', colorKeys);
// ["RED","ORANGE","YELLOW","GREEN","BLUE","INDIGO","VIOLET"]

const colorValues = Object.values(Color);
console.log('colorValues =', colorValues);
// ["Red","Orange","Yellow","Green","Blue","Indigo","Violet"]

colorKeys.map(colorKey => {
  console.log(`color key = ${colorKey}, value = ${Color[colorKey]}`);
});
/*
color key = RED, value = Red
color key = ORANGE, value = Orange
color key = YELLOW, value = Yellow
color key = GREEN, value = Green
color key = BLUE, value = Blue
color key = INDIGO, value = Indigo
color key = VIOLET, value = Violet
*/

TypeScript 플레이 그라운드에서 온라인 예제 보기

(*) 이전 브라우저에 필요한 Polyfill은 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values#Browser_compatibility를 참조 하십시오.


TypeScript (생각 : 리플렉션)에는 RTTI (런타임 유형 정보)의 개념이 없으므로이를 수행하려면 트랜스 파일 된 JavaScript에 대한 지식이 필요합니다. 따라서 TypeScript 0.95를 가정합니다.

enum MyEnum {
    First, Second, Third
}

된다 :

var MyEnum;
(function(MyEnum) {
    MyEnum[MyEnum["First"] = 0] = "First";
    MyEnum[MyEnum["Second"] = 1] = "Second";
    MyEnum[MyEnum["Third"] = 2] = "Third";
}

그래서,이 자바 스크립트에서 정규 객체로 모델링 MyEnum.0 == "First"하고 MyEnum.First == 0. 따라서 모든 열거 형 이름을 열거하려면 개체에 속하고 숫자가 아닌 모든 속성을 가져와야합니다.

for (var prop in MyEnum) {         
    if (MyEnum.hasOwnProperty(prop) &&
        (isNaN(parseInt(prop)))) {
        console.log("name: " + prop);
    }
}

좋아, 이제 어떻게해야하는지 말씀 드렸으니 이것이 나쁜 생각이라고 말씀 드릴 수 있습니다 . 관리 언어를 작성하지 않기 때문에 이러한 습관을 가져올 수 없습니다. 여전히 평범한 오래된 JavaScript입니다. 어떤 종류의 선택 목록을 채우기 위해 JavaScript의 구조를 사용하려면 평범한 오래된 배열을 사용합니다. 열거 형은 여기서 올바른 선택이 아닙니다. TypeScript의 목표는 관용적이고 예쁜 JavaScript를 생성하는 것입니다. 이런 방식으로 열거 형을 사용하면이 목표가 유지되지 않습니다.


열거 형의 이름과 인덱스를 가져 오는 함수를 추가 할 수 있습니다.

enum MyEnum {
  First,
  Second,
  Third
}

namespace MyEnum {
  function isIndex(key):boolean {
    const n = ~~Number(key);
    return String(n) === key && n >= 0;
  }

  const _names:string[] = Object
      .keys(MyEnum)
      .filter(key => !isIndex(key));

  const _indices:number[] = Object
      .keys(MyEnum)
      .filter(key => isIndex(key))
      .map(index => Number(index));

  export function names():string[] {
    return _names;
  }

  export function indices():number[] {
    return _indices;
  }
}

console.log("MyEnum names:", MyEnum.names());
// Prints: MyEnum names: ["First", "Second", "Third"]

console.log("MyEnum indices:", MyEnum.indices());
// Prints: MyEnum indices: [0, 1, 2]

Note that you could just export the _names and _indices consts rather than exposing them through an exported function, but because the exported members are members of the enum it is arguably clearer to have them as functions so they are not confused with the actual enum members.

It would be nice if TypeScript generated something like this automatically for all enums.


I used the solution proposed by David Sherret and wrote an npm library you can use named enum-values...

Git: enum-values

// Suppose we have an enum
enum SomeEnum {
  VALUE1,
  VALUE2,
  VALUE3
}

// names will be equal to: ['VALUE1', 'VALUE2', 'VALUE3']
var names = EnumValues.getNames(SomeEnum);

// values will be equal to: [0, 1, 2]
var values = EnumValues.getValues(SomeEnum);

enum MyEnum {
    First, Second, Third, NUM_OF_ENUMS
}

for(int i = 0; i < MyEnum.NUM_OF_ENUMS; ++i) {
    // do whatever you need to do.
}

A one-liner to get a list of entries (key-value objects/pairs):

Object.keys(MyEnum).filter(a=>a.match(/^\D/)).map(name=>({name, value: MyEnum[name] as number}));

If you want to associate strings values to your enum these methods don't works. To have a generic function you can do :

function listEnum(enumClass) {
    var values = [];
    for (var key in enumClass) {
        values.push(enum[key]);
    }
    values.length = values.length / 2;
    return values;
}

It's works because TypeScript will add keys in first step, and values in second step.

In TypeScript it's:

var listEnums = <T> (enumClass: any): T[]=> {
    var values: T[] = [];
    for (var key in enumClass) {
        values.push(enumClass[key]);
    }
    values.length = values.length / 2;
    return values;
};

var myEnum: TYPE[] = listEnums<TYPE>(TYPE);

joe's answer just made me realize that is much more easier to rely on the first N numeric keys than making more complex testings:

function getEnumMembers(myEnum): string[]
{
    let members = []
    for(let i:number = 0; true; i++) {
        if(myEnum[i] === undefined) break
        members.push(myEnum[i])
    }

    return members
}

enum Colors {
    Red, Green, Blue
}

console.log(getEnumMembers(myEnum))

참고URL : https://stackoverflow.com/questions/21293063/how-to-programmatically-enumerate-an-enum-type

반응형