প্রোগ্রামিয়ালি একটি এনাম টাইপ গণনা করবেন কীভাবে?


90

বলুন যে আমার কাছে টাইপস্ক্রিপ্ট রয়েছে enum, নীচে MyEnum:

enum MyEnum {
    First,
    Second,
    Third
}

enumমানগুলির একটি অ্যারে উত্পাদন করার জন্য টাইপস্ক্রিপ্ট ০.৯.৫ এর সর্বোত্তম উপায় কী হবে ? উদাহরণ:

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

উত্তর:


192

এটি সেই এনামের জাভাস্ক্রিপ্ট আউটপুট:

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

যা এর মতো একটি বিষয়:

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

স্ট্রিং মান সহ এনাম সদস্যগণ

টাইপসক্রিপ্ট ২.৪ এনামের পক্ষে স্ট্রিং এনাম সদস্যের মানগুলি যুক্ত করার ক্ষমতা যুক্ত করেছে। সুতরাং নীচের মতো দেখতে এমন এনাম দিয়ে শেষ করা সম্ভব:

enum MyEnum {
    First = "First",
    Second = 2,
    Other = "Second"
}

// compiles to
var MyEnum;
(function (MyEnum) {
    MyEnum["First"] = "First";
    MyEnum[MyEnum["Second"] = 2] = "Second";
    MyEnum["Other"] = "Second";
})(MyEnum || (MyEnum = {}));

সদস্যের নাম প্রাপ্তি

এনাম সদস্যদের কীভাবে পাবেন তা জানার চেষ্টা করার জন্য আমরা উপরের উদাহরণটি অবিলম্বে দেখতে পারি:

{
    "2": "Second",
    "First": "First",
    "Second": 2,
    "Other": "Second"
}

আমি এখানে যা এলাম তা এখানে:

const e = MyEnum as any;
const names = Object.keys(e).filter(k => 
    typeof e[k] === "number"
    || e[k] === k
    || e[e[k]]?.toString() !== k
);

সদস্য মান

একবার, আমাদের নামগুলি থাকলে, আমরা এগুলি করে লুপটি আনতে পারি:

const values = names.map(k => MyEnum[k]);

এক্সটেনশন ক্লাস

আমি মনে করি এটি করার সর্বোত্তম উপায় হ'ল আপনার নিজস্ব ফাংশন তৈরি করা (উদাঃ EnumEx.getNames(MyEnum))। আপনি এনামে কোনও ফাংশন যোগ করতে পারবেন না।

class EnumEx {
    private constructor() {
    }

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

    static getNames(e: any) {
        return Object.keys(e).filter(k => 
            typeof e[k] === "number"
            || e[k] === k
            || e[e[k]]?.toString() !== k
        );
    }

    static getValues(e: any) {
        return EnumEx.getNames(e).map(n => e[n] as string | number);
    }
}

কৌতূহলজনকভাবে (কারণ অনেক লোক এই উত্তরটিকে অগ্রাহ্য করেছে ), আমি টিএস খেলার মাঠে এটি কাজ করতে পারি না: সংক্ষিপ্ত.আর / জেজে 8 জি 2 আমি কি কোনও ভুল করছি?
পিটার

4
@ পিটার আমি স্ট্রিং এনামগুলি সম্পর্কিত তথ্য অন্তর্ভুক্ত করার জন্য উত্তর আপডেট করেছি। এছাড়াও, আপনি একটি এর for ofপরিবর্তে একটি বিবৃতি ব্যবহার করতে চাইবেনfor in
ডেভিড শেরেট

24

সঙ্গে টাইপ করা বিষয়> = 2.4 আপনি STRING 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"
}

সুতরাং, স্ট্রিং এনামগুলির ক্ষেত্রে জিনিসগুলিকে ফিল্টার করার দরকার নেই Object.keys(Color)এবং Object.values(Color)(*) যথেষ্ট:

const colorKeys = Object.keys(Color) as (keyof typeof 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/ উল্লেখ / গ্লোবাল_অবজেক্টস / অবজেক্ট / মূল্যগুলি# ব্রাউজার_সামগ্রিকতা দেখুন


এতে ত্রুটি রয়েছেElement implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof Color'. No index signature with a parameter of type 'string' was found on type 'typeof Color'.
জোনাস

4
@ জোনাস আমি এটি একটি কাস্ট দিয়ে স্থির করেছি:Object.keys(Color) as (keyof typeof Color)[]
টাঙ্গুয়_কি

মহান, আপনাকে ধন্যবাদ!
জোনাস

9

এনামের নাম এবং সূচকগুলি পেতে আপনি ফাংশন যুক্ত করতে পারেন:

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একটি রপ্তানি ফাংশন মাধ্যমে তাদের প্রকাশক বদলে consts, কিন্তু রপ্তানি সদস্যদের enum সদস্য এটা তর্কসাপেক্ষ তাদের ফাংশন হিসেবে পেয়ে তাই তারা প্রকৃত enum সদস্যদের সঙ্গে গুলিয়ে ফেলা হয় পরিষ্কার হয়।

এটি ভাল হবে যদি টাইপস্ক্রিপ্টটি সমস্ত এনামগুলির জন্য স্বয়ংক্রিয়ভাবে এমন কিছু উত্পন্ন করে।


7

টাইপস্ক্রিপ্টে আরটিটিআই (রানটাইম টাইপ তথ্য) সম্পর্কে ধারণা নেই (তাই: প্রতিফলন) সুতরাং এটি করতে, স্থানান্তরিত জাভাস্ক্রিপ্টের জ্ঞান প্রয়োজন। সুতরাং, টাইপস্ক্রিপ্ট ০.৯৯ অনুমান করে:

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

ঠিক আছে, সুতরাং এখন আমি আপনাকে এটি কীভাবে করব তা বললাম, এটি আপনাকে একটি খারাপ ধারণা বলে জানার অনুমতি দেওয়া হয়েছে । আপনি কোনও পরিচালিত ভাষা লিখছেন না, তাই আপনি এই অভ্যাসগুলি আনতে পারবেন না। এটি এখনও সাদামাটা পুরানো জাভাস্ক্রিপ্ট। যদি আমি জাভাস্ক্রিপ্টে কোনও কাঠামো কোনও ধরণের পছন্দ তালিকাসমূহের জন্য ব্যবহার করতে চাইতাম তবে আমি একটি সরল পুরানো অ্যারে ব্যবহার করব। একটি এনাম এখানে সঠিক পছন্দ নয়, পাং উদ্দেশ্যে। টাইপস্ক্রিপ্টের লক্ষ্য হ'ল প্রতিচ্ছবিযুক্ত, দুর্দান্ত জাভাস্ক্রিপ্ট তৈরি করা। এনামগুলি এভাবে ব্যবহার করা এই লক্ষ্যটি সংরক্ষণ করে না।


5

আমি ডেভিড শেরেটের প্রস্তাবিত সমাধানটি ব্যবহার করেছিলাম এবং একটি এনপিএম গ্রন্থাগার লিখেছিলাম যা আপনি নাম ব্যবহার করতে পারেন 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);

3

প্রবেশের তালিকা (কী-মান অবজেক্টস / জুড়ি) পেতে একটি ওয়ান-লাইনার:

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

2
enum MyEnum {
    First, Second, Third, NUM_OF_ENUMS
}

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

4
এটি কেবল তখনই কাজ করে যদি আপনার এনাম কোনও মান সংজ্ঞায়িত না করে (এটি ভাল প্যাকড এবং ইনক্রিমেন্টাল)। উদাহরণস্বরূপ এনাম মানগুলি "প্রথম = 0x1000" বা "পেজ নটফাউন্ড = 404" হতে পারে। NUM_OF_ENUMS সর্বদা বৃহত্তম সংজ্ঞায়িত মানের চেয়ে বড় হবে, সুতরাং আমার উদাহরণগুলিতে 0x1001 বা 405।
আকু

2

আপনি যদি আপনার এনামের সাথে স্ট্রিংয়ের মানগুলি সংযুক্ত করতে চান তবে এই পদ্ধতিগুলি কার্যকর হয় না। জেনেরিক ফাংশন রাখতে আপনি করতে পারেন:

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

1

জো এর উত্তর আমাকে ঠিক বুঝতে পেরেছিল যে আরও জটিল টেস্টিংয়ের চেয়ে প্রথম এন সংখ্যার কীগুলিতে নির্ভর করা অনেক বেশি সহজ:

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

4
এটি একটি বিপজ্জনক ধারণা, কারণ এনামগুলিকে নির্ধারিত মানগুলি সংজ্ঞায়িত করা সম্ভব এবং সেগুলি বৃদ্ধি এবং ভাল প্যাক করার দরকার নেই। এটা বিরল উদাহরণস্বরূপ একটি enum মধ্যে বিট মাস্ক দেখতে সম্ভবত যে 400 এ শুরু এইচটিএমএল এরর কোড একটি টেবিল, বা
Aku থেকে



0

একটি এনামের উপরে আইট্রেট করা

স্ট্রিং এনামগুলি এর জন্য সবচেয়ে ভাল ব্যবহৃত হয়। এখানে একটি উদাহরণ:

// This is a string enum
enum MyEnum {
    First = 'First',
    Second = 'Second',
    Third = 'Third',
}

// An enum is a TS concept
// However his MyEnum compiles to JS object:
//  {
//   "First": "First",
//   "Second": "Second",
//   "Third": "Third"
// } 


// Therefore we can get the keys in the following manner:
const keysArray = Object.keys(MyEnum);

for (const key of keysArray) {
    console.log(key)
}
// [LOG]: "First" 
// [LOG]: "Second" 
// [LOG]: "Third" 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.