सवाल टाइपस्क्रिप्ट 0.9.5 में प्रोग्रामिंग रूप से एनम प्रकार का आकलन कैसे करें?


मान लें कि मेरे पास टाइपस्क्रिप्ट एनम है, माईएनम, निम्नानुसार है:

enum MyEnum {
    First,
    Second,
    Third
}

Enum मानों की सरणी बनाने के लिए टाइपस्क्रिप्ट 0.9.5 में सबसे अच्छा तरीका क्या होगा? उदाहरण:

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

69
2018-01-22 20:15


मूल




जवाब:


यह उस enum का जावास्क्रिप्ट आउटपुट है:

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"]

सदस्य मूल्य

Enum सदस्य मान प्राप्त करने के दौरान, हम ऑब्जेक्ट के मानों को किसी भी संख्या से फ़िल्टर कर सकते हैं:

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

शामिल हैं: [0, 1, 2]

विस्तार कक्षा

मुझे लगता है कि ऐसा करने का सबसे अच्छा तरीका अपने स्वयं के कार्यों को बनाना है (उदा। EnumEx.getNames(MyEnum))। आप एक enum में एक समारोह नहीं जोड़ सकते हैं।

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[];
    }
}

171
2018-01-22 22:01



अजीब बात यह है कि बदल रहा है Object.keys(MyEnum).map(k => MyEnum[k]) साथ में Object.values(MyEnum) टाइपस्क्रिप्ट शिकायत करने का कारण बनता है - Yi Jiang


साथ में टाइपस्क्रिप्ट> = 2.4 आप स्ट्रिंग enums परिभाषित कर सकते हैं:

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

जावास्क्रिप्ट 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"
}

इस प्रकार, स्ट्रिंग enums के मामले में, चीजों को फ़िल्टर करने की कोई ज़रूरत नहीं है, 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
*/

ऑनलाइन देखें टाइपस्क्रिप्ट खेल का मैदान पर उदाहरण

(*) पुराने ब्राउज़र के लिए आवश्यक पॉलीफिल, देखें https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values#Browser_compatibility


9
2017-09-17 22:41



यह मानता है कि आपके पास है enum { Red = "Red" }, और नहीं enum { RED = "Red" } - tommyTheHitMan
टिप्पणी के लिए @tommyTheHitMan thx, मैंने अपना जवाब संपादित कर लिया है - tanguy_k
संपत्ति 'मूल्य' प्रकार 'ऑब्जेक्ट कॉन्स्ट्रक्टर' पर मौजूद नहीं है। - Mahmoud Shahoud
@ महमूदशहौद स्पष्ट रूप से आपको एक पॉलीफिल की आवश्यकता है Object.values() पुराने ब्राउज़र का उपयोग करते समय: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - tanguy_k


टाइपस्क्रिप्ट (सोच: प्रतिबिंब) में आरटीटीआई (रनटाइम प्रकार की जानकारी) की कोई अवधारणा नहीं है ताकि ऐसा करने के लिए, पारदर्शी जावास्क्रिप्ट का ज्ञान आवश्यक हो। तो, टाइपस्क्रिप्ट 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। इसलिए, सभी enum नामों को गिनने के लिए, आपको ऑब्जेक्ट से संबंधित सभी गुणों को प्राप्त करने की आवश्यकता है और यह भी संख्याएं नहीं हैं:

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

ठीक है, तो अब मैंने आपको बताया है कि यह कैसे करना है, मुझे आपको बताने की अनुमति है यह विचार अच्छा नहीं है। आप एक प्रबंधित भाषा नहीं लिख रहे हैं, इसलिए आप इन आदतों को नहीं ला सकते हैं। यह अभी भी सिर्फ पुरानी पुरानी जावास्क्रिप्ट है। अगर मैं किसी प्रकार की पसंद सूची को पॉप्युलेट करने के लिए जावास्क्रिप्ट में एक संरचना का उपयोग करना चाहता था, तो मैं एक सादे पुरानी सरणी का उपयोग करूंगा। एक enum यहां सही विकल्प नहीं है, इरादा इरादा है। टाइपस्क्रिप्ट का लक्ष्य मूर्खतापूर्ण, सुंदर जावास्क्रिप्ट उत्पन्न करना है। इस तरह से enums का उपयोग इस लक्ष्य को संरक्षित नहीं करता है।


9
2018-01-22 22:42



परिप्रेक्ष्य के लिए धन्यवाद - यह भी एक अच्छा जवाब है। मैं सामान्य रूप से Enums का उपयोग करने पर अपनी नजर रखूंगा; निश्चित रूप से सादे पुरानी सरणी का लाभ देखें। मैं सी # के सीधी बंदरगाह पर काम कर रहा हूं, जैसा कि आपने शायद अनुमान लगाया था ... इस समय स्थिर मूल्य को एनम मूल्यों की जांच करने के लिए अच्छा लगा। जब मैं जावास्क्रिप्ट सम्मेलनों, प्रथाओं के साथ अधिक स्वाभाविक रूप से संरेखित करने के लिए कोड संशोधित करता हूं तो इस पर एक कठोर नज़र डालेंगे। - David Cuccia


आप enum के नाम और सूचकांक प्राप्त करने के लिए फ़ंक्शंस जोड़ सकते हैं:

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]

ध्यान दें कि आप सकता है बस निर्यात करें _names तथा _indices निर्यात किए गए फ़ंक्शन के माध्यम से उन्हें उजागर करने के बजाए, लेकिन निर्यातित सदस्य enum के सदस्य हैं, इसलिए यह तर्कसंगत रूप से उन्हें कार्य के रूप में स्पष्ट करने के लिए स्पष्ट है ताकि वे वास्तविक enum सदस्यों से भ्रमित न हों।

यह अच्छा होगा अगर टाइपस्क्रिप्ट ने सभी enums के लिए स्वचालित रूप से ऐसा कुछ उत्पन्न किया।


8
2018-05-23 13:36



दिलचस्प, धन्यवाद। अगर मैं सही ढंग से समझता हूं, तो आप एंटीम टाइप नाम मिररिंग स्थिर विधि कॉल के लिए MyEnum नेमस्पेस का उपयोग कर रहे हैं, जो कि मेरे स्वामित्व वाले प्रकारों के लिए भी काम करेगा। अगर यह सामान्य बनाया जा सकता है ... - David Cuccia
इंडेक्स () को सरल बनाया जा सकता है? - मैं इसका उपयोग कर रहा हूं: `` `फ़ंक्शन है इंडेक्स (कुंजी: स्ट्रिंग): बूलियन {रिटर्न! IsNaN (<any> key); } `` ` - Sean


मैंने डेविड शेरेट द्वारा प्रस्तावित समाधान का उपयोग किया और एक एनपीएम लाइब्रेरी लिखी जिसे आप नामित कर सकते हैं enum-values...

गिट: 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);

4
2017-07-23 10:24





enum MyEnum {
    First, Second, Third, NUM_OF_ENUMS
}

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

2
2018-05-27 21:49



यह केवल तभी काम करता है जब आपका enum किसी भी मान को परिभाषित नहीं करता है (यह अच्छी तरह से पैक और वृद्धिशील है)। उदाहरण के लिए एनम मान "फर्स्ट = 0x1000" या "पेज नॉटफाउंड = 404" हो सकते हैं। NUM_OF_ENUMS हमेशा मेरे उदाहरणों में सबसे बड़ा परिभाषित मान, 0x1001 या 405 से अधिक होगा। - Aku


यदि आप स्ट्रिंग मानों को अपने enum से जोड़ना चाहते हैं तो ये विधियां काम नहीं करती हैं। एक सामान्य कार्य करने के लिए आप कर सकते हैं:

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

यह काम करता है क्योंकि टाइपस्क्रिप्ट पहले चरण में कुंजी जोड़ देगा, और दूसरे चरण में मान।

टाइपस्क्रिप्ट में यह है:

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);

2
2018-05-25 09:02



-1 आपको यह नहीं मानना ​​चाहिए कि सिर्फ इसलिए कि गुण एक ही तरीके से जोड़े गए थे, ताकि वे उसी क्रम में पुनरावृत्त हो जाएंगे। देख stackoverflow.com/questions/5525795/... - Juan Mendes