আমি কীভাবে একটি স্ট্রিংকে টাইপস্ক্রিপ্টে এনামে রূপান্তর করব?


310

আমি টাইপস্ক্রিপ্টে নিম্নলিখিত এনাম সংজ্ঞায়িত করেছি:

enum Color{
    Red, Green
}

এখন আমার ফাংশনে আমি স্ট্রিং হিসাবে রঙ পাই। আমি নিম্নলিখিত কোড চেষ্টা করেছি:

var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum

আমি কীভাবে এই মানটিকে একটি এনামে রূপান্তর করতে পারি?

উত্তর:


429

টাইপস্ক্রিপ্ট ০.৯ এ এনামগুলি স্ট্রিং + সংখ্যা ভিত্তিক। সাধারণ রূপান্তরগুলির জন্য আপনার টাইপ প্রতিরক্ষার প্রয়োজন হবে না:

enum Color{
    Red, Green
}

// To String
 var green: string = Color[Color.Green];

// To Enum / number
var color : Color = Color[green];

এটি অনলাইনে চেষ্টা করুন

আমার ওএসএস বইতে এই এবং অন্যান্য এনুম ধরণের সম্পর্কে আমার কাছে ডকুমেন্টেশন রয়েছে: https://basarat.gitbook.io/typescript/type-system/enums


111
এটি --noImplicitAny(ভিএসে চেক না করা "অন্তর্ভুক্ত 'কোনও' প্রকারের অনুমতি দিন") দিয়ে কাজ করে না । এটি error TS7017: Index signature of object type implicitly has an 'any' type.আমার জন্য এটি কাজ করেছে: var color: Color = (<any>Color)[green];(সংস্করণ 1.4 সহ পরীক্ষিত)
ভোজটা 19

3
@ ভোজটা ঠিক বলেছেন। এটি ভিএস ২০১২-তে কাজ করছে না This এই রঙটি কিন্তু বর্ণের রঙে কাজ করেছে: রঙ = (<বিভিন্ন> রঙ) [সবুজ];
ফয়সাল এমকিউ

3
এটি এখানেও কাজ করে না, অফিসিয়াল ডকুমেন্টেশনের মাধ্যমে এটি নিশ্চিত হয়ে যায়: টাইপসক্রিপ্টএলআর.জি.
পিটার ডি বিয়

26
এটি যদি নিশ্চিত না হনvar color : Color = Color[green as keyof typeof Color];
জোনাস

2
@ Naxos84 দেখুন আমার answear stackoverflow.com/a/56076148/294242
জোনাস

122

টাইপসক্রিপ্ট হিসাবে এনমগুলিতে ২.১ স্ট্রিং কীগুলি দৃ strongly়ভাবে টাইপ করা হয়। keyof typeofউপলব্ধ স্ট্রিং কী ( 1 ) সম্পর্কিত তথ্য পেতে ব্যবহৃত হয় :

enum Color{
    Red, Green
}

let typedColor: Color = Color.Green;
let typedColorString: keyof typeof Color = "Green";

// Error "Black is not assignable ..." (indexing using Color["Black"] will return undefined runtime)
typedColorString = "Black";

// Error "Type 'string' is not assignable ..." (indexing works runtime)
let letColorString = "Red";
typedColorString = letColorString;

// Works fine
typedColorString = "Red";

// Works fine
const constColorString = "Red";
typedColorString = constColorString

// Works fine (thanks @SergeyT)
let letColorString = "Red";
typedColorString = letColorString as keyof typeof Color;

typedColor = Color[typedColorString];

https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types


4
সুতরাং আমরা টাইপকাস্ট ব্যবহার করতে পারি:let s = "Green"; let typedColor = <keyof typeof Color> s;
সার্জিয়েট

হাঁ, এবং প্রতিস্থাপন letসঙ্গে constভোটদান ছাড়া ইচ্ছা হবে। এটি পরিষ্কার করার জন্য আপডেট হওয়া উদাহরণ। ধন্যবাদ @ সার্জিটি
ভিক্টর

1
typedColorString = Color["Black"];এখন ফিরে আসেerror TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'
ডোমিনিক

2
একটি লাইনের উত্তর:const color: Color = Color[colorString as keyof typeof Color];
Nov

38

আপনি যদি নিশ্চিত হন যে ইনপুট স্ট্রিংয়ের রঙ এনামের সাথে হুবহু মিল রয়েছে তবে ব্যবহার করুন:

const color: Color = (<any>Color)["Red"];

যে ক্ষেত্রে ইনপুট স্ট্রিং এনুমের সাথে মেলে না, সেই ক্ষেত্রে ব্যবহার করুন:

const mayBeColor: Color | undefined = (<any>Color)["WrongInput"];
if (mayBeColor !== undefined){
     // TypeScript will understand that mayBeColor is of type Color here
}

খেলার মাঠ


আমরা যদি নিক্ষেপ না enumকরতে <any>তারপর টাইপ করুন টাইপ করা বিষয় ত্রুটি দেখাবে:

এলিমেন্টের স্পষ্টতই 'কোনও' টাইপ রয়েছে কারণ সূচক এক্সপ্রেশনটি 'সংখ্যার' নয়।

এর অর্থ হ'ল ডিফল্টরূপে টাইপস্ক্রিপ্ট এনাম টাইপ সংখ্যা সূচকগুলির সাথে কাজ করে let c = Color[0], তবে স্ট্রিং সূচকগুলির মতো নয় let c = Color["string"]। এটি আরও সাধারণ ইস্যু অবজেক্ট স্ট্রিং সূচকগুলির জন্য মাইক্রোসফ্ট টিমের একটি পরিচিত বিধিনিষেধ ।


আপনি <কীফ টাইপফোন রঙ> এ কাস্ট করতে পারেন। এছাড়াও "0" ভুল ইনপুটও কিন্তু অপরিজ্ঞাতিত ফিরে আসবে না, সুতরাং টাইপ মে মেবেকলার === 'সংখ্যা' পরীক্ষা করুন
কোয়ান্টিন 2

@ কোয়ান্টিন 2 একটি সংখ্যার স্ট্রিং সম্পর্কে কি? অর্থাত্ typeof '0'হওয়া উচিতstring
প্যাট্রিক মাইকেলসেন

36
enum Color{
    Red, Green
}

// To String
 var green: string = Color[Color.Green];

// To Enum / number
var color : Color = Color[green as keyof typeof Color]; //Works with --noImplicitAny

এই উদাহরণটি --noImplicitAnyটাইপস্ক্রিপ্টে কাজ করে

সূত্র:
https://github.com/Mic Microsoft/TypeScript/issues/ 13775# issuecomment- 276381229 https://www.typescriptlang.org/docs/handbook/advanced-tyype.html#index-tyype


আমি জানি না কেন, কিন্তু এই সমাধান উপর কাজ করে না const enum (টাইপ করা বিষয় 3.8.3 ব্যবহার করে)
রবিন-hoodie

30

এই নোটটি মূল প্রশ্নের সাথে নয়, বাসরতের উত্তরের সাথে সম্পর্কিত ।

আমার নিজের প্রকল্পে আমার একটি বিজোড় সমস্যা ছিল যেখানে কম্পাইলার এই কোডটির সমতুল্য ব্যবহার করে "স্ট্রিংকে রঙিন রূপান্তর করতে পারে না" এর সমান একটি ত্রুটি দিচ্ছিল:

var colorId = myOtherObject.colorId; // value "Green";
var color: Color = <Color>Color[colorId]; // TSC error here: Cannot convert string to Color.

আমি দেখতে পেলাম যে সংকলক প্রকারের ইনফারেন্সিং বিভ্রান্ত হয়ে পড়েছিল এবং এটি ভেবেছিল যে colorIdএটি একটি এনাম মান এবং কোনও আইডি নয়। সমস্যাটি সমাধান করতে আমাকে আইডিটি স্ট্রিং হিসাবে কাস্ট করতে হয়েছিল:

var colorId = <string>myOtherObject.colorId; // Force string value here
var color: Color = Color[colorId]; // Fixes lookup here.

আমি নিশ্চিত না যে কী কারণে সমস্যা হয়েছে তবে আমি যদি এই সমস্যাটি ঘটায় তবে কেউ এই সমস্যাটি নিয়ে গেলে আমি এই নোটটি এখানে রেখে দেব।


ধন্যবাদ! এটি একটি সুন্দর নির্বোধ সমস্যা এবং সমস্যাটি কী তা বোঝা মুশকিল ay
চিকেনফিট

24

আমি নিম্নলিখিত কোড ব্যবহার করে এটি কাজ করেছিলাম।

var green= "Green";
var color : Color= <Color>Color[green];

23

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

enum Color {
  Green = "Green",
  Red = "Red"
}

const color = "Green";
const colorEnum = color as Color;

1
খুব সহজ. নিস!
বার্নোল্লি IT

1
পারফেক্ট .... :-)
জাকেন এই’ঘর

1
এটি বিভ্রান্তিকর হতে পারে কারণ এটি অবৈধ রঙগুলির বিরুদ্ধে রক্ষা করে না। const colorEnum = "Blue" as Colorত্রুটি হবে না, এবং আপনি colorEnumঠিক আছে তা ভেবেই ছেড়ে চলে যাবেন । তবে আপনি যদি console.logএটির কাছে থাকেন তবে আপনি "নীল" দেখতে পাবেন। আর্টুর উত্তরটি দুর্দান্ত , কারণ colorEnumহবে undefined- এবং তারপরে আপনি এটির জন্য বিশেষভাবে পরীক্ষা করতে পারেন।
এম ফালঙ্গা

20

আপনি টাইপস্ক্রিপ্ট ব্যবহার করেছেন: উপরের সমাধানগুলির অনেকগুলি কাজ না করে বা অত্যধিক জটিল।

পরিস্থিতি : স্ট্রিংগুলি এনাম মানগুলির মতো নয় (কেসিং পৃথক হয়)

enum Color {
  Green = "green",
  Red = "red"
}

শুধু ব্যবহার করুন:

const color = "green" as Color

15

আমি একই সংকলক ত্রুটি মধ্যে দৌড়ে। স্লি_কার্ডিনালের পদ্ধতির সামান্য সংক্ষিপ্ততম প্রকরণ।

var color: Color = Color[<string>colorId];

সংযোজন হিসাবে: আপনার কাছে একটি জাভাস্ক্রিপ্ট স্তর দ্বারা পূর্ণ টাইপস্ক্রিপ্ট এনুম রয়েছে যা এনামকে স্ট্রিং হিসাবে সিরিয়ালযুক্ত করেছে (উদাহরণস্বরূপ অ্যাঙ্গুলারজেএস এর মাধ্যমে এসপি ওয়েব এপিআই বলুন) আপনি myProp.color = Color[<string><any>myProp.color] চিয়ার্স করতে পারেন
ভিক্টর

1
এটি অবশ্যই স্বীকৃত উত্তর হতে হবে।
মিরোস্লাভ পপভ

9

যদি টাইপস্ক্রিপ্ট সংকলক জানেন যে ভেরিয়েবলের ধরণটি স্ট্রিং হয় তবে এটি কাজ করে:

let colorName : string = "Green";
let color : Color = Color[colorName];

অন্যথায় আপনার স্পষ্টভাবে এটিকে একটি স্ট্রিংয়ে রূপান্তর করা উচিত (সংকলক সতর্কতা এড়ানোর জন্য):

let colorName : any = "Green";
let color : Color = Color["" + colorName];

রানটাইম এ উভয় সমাধান কাজ করবে।


3
শুধু <string>colorNameপরিবর্তে টাইপাস্টাস্ট ব্যবহার করবেন না কেন "" + colorName?
সার্জিয়েট

7

এই প্রশ্নে প্রচুর মিশ্র তথ্য রয়েছে, সুতরাং টাইপস্ক্রিপ্টের সাথে মডেলগুলিতে এনামগুলি ব্যবহারের নিকের গাইডে টাইপস্ক্রিপ্ট ২.x + এর সম্পূর্ণ প্রয়োগটি কভার করা যাক

এই গাইডটি হ'ল: লোকেরা ক্লায়েন্ট-সাইড কোড তৈরি করছে যা সার্ভার থেকে পরিচিত স্ট্রিংগুলির একটি সেট ইনজেস্ট করছে যা ক্লায়েন্টের পক্ষে এনাম হিসাবে সহজেই মডেল করা হবে।

এনাম সংজ্ঞায়িত করুন

এনাম দিয়ে শুরু করা যাক। এটি দেখতে কিছু দেখতে হবে:

export enum IssueType {
  REPS = 'REPS',
  FETCH = 'FETCH',
  ACTION = 'ACTION',
  UNKNOWN = 'UNKNOWN',
}

এখানে দুটি বিষয় লক্ষ্য করুন:

  1. আমরা এগুলিকে স্পষ্টভাবে স্ট্রিং-ব্যাকড এনাম কেস হিসাবে ঘোষণা করছি যা আমাদের এগুলি স্ট্রিং দিয়ে ইনস্ট্যান্ট করার অনুমতি দেয়, অন্য কোনও সম্পর্কযুক্ত নয় not

  2. আমরা একটি বিকল্প বা আমাদের সার্ভারে মডেলের উপর অস্তিত্ব নাও থাকতে পারে জুড়েছে করেছি: UNKNOWN। এটি undefinedআপনি পছন্দ করেন এমনভাবে পরিচালনা করা যেতে পারে , তবে | undefinedহ্যান্ডলিংকে সহজ করার জন্য যখনই সম্ভব হয় তবে এগুলি এড়ানো পছন্দ করি ।

একটি সম্পর্কে দুর্দান্ত জিনিস UNKNOWNকেস ক্ষেত্রে হ'ল আপনি কোড সম্পর্কে এ সম্পর্কে প্রকৃতপক্ষে স্পষ্ট হতে পারেন এবং অজানা এনাম কেসগুলির জন্য শৈলী তৈরি করতে পারেন উজ্জ্বল লাল এবং পলকযুক্ত যাতে আপনি জানেন যে আপনি কোনও কিছু সঠিকভাবে পরিচালনা করছেন না।

এনামকে পার্স করুন

আপনি এই এনামটি অন্য কোনও মডেল বা এমনি এম্বেড এম্বেড ব্যবহার করতে পারেন তবে আপনি জেএসওএন বা এক্সএমএল (হা) থেকে স্ট্রিং-ওয়াই টাইপ করা এনুমকে আপনার দৃ strongly়ভাবে টাইপ করা অংশে পার্স করতে চলেছেন। যখন অন্য কোনও মডেল এম্বেড করা হয়, তখন এই পার্সার ক্লাস কনস্ট্রাক্টরে থাকে।

parseIssueType(typeString: string): IssueType {
  const type = IssueType[typeString];
  if (type === undefined) {
    return IssueType.UNKNOWN;
  }

  return type;
}

এনামটি সঠিকভাবে পার্স করা থাকলে এটি সঠিক ধরণের হিসাবে শেষ হবে। অন্যথায়, এটি হবে undefinedএবং আপনি এটিকে আটকাতে এবং আপনার কেসটি ফিরিয়ে দিতে পারেন UNKNOWN। আপনি যদি undefinedনিজের অজানা কেস হিসাবে ব্যবহার করতে পছন্দ করেন তবে এনাম পার্সিংয়ের চেষ্টা থেকে আপনি কেবল কোনও ফলাফল দিতে পারবেন।

সেখান থেকে, পার্স ফাংশনটি ব্যবহার করার এবং আপনার নতুন শক্তিশালী টাইপড ভেরিয়েবলটি ব্যবহার করার বিষয়টি কেবলমাত্র।

const strongIssueType: IssueType = parseIssueType('ACTION');
// IssueType.ACTION
const wrongIssueType: IssueType = parseIssueType('UNEXPECTED');
// IssueType.UNKNOWN

6
দুর্ভাগ্যক্রমে, এটি সঠিক বা কমপক্ষে, সাধারণীকরণযোগ্য নয় বলে মনে হয়। এটি কাজ করে কারণ আপনার কীগুলি তাদের অর্পিত স্ট্রিংগুলির সমান করে। তারা, আমার ক্ষেত্রে মত যদি, পৃথক, তবে, এটি কাজ করে না। ডকুমেন্টেশনের কথায় : "মনে রাখবেন স্ট্রিং এনাম সদস্যরা মোটেই উত্পন্ন বিপরীত ম্যাপিং পান না।" আপনার কোডটি এমন কিছু সংকলন করবে IssueType["REPS"]="REPS"। আপনি যদি নিজের এনামটিকে কিছুটা আলাদাভাবে সংজ্ঞায়িত করেন, বলুন, REPS="reps"IssueType["REPS"]="reps"
এটির

... সর্বদা ফিরে আসুন IssueType.UNKNOWNকারণ repsআপনার এনামের কোনও চাবি নেই । খুব খারাপ, আমি এখনও এর জন্য কোনও কার্যকরী সমাধান খুঁজে পাইনি কারণ আমার স্ট্রিংগুলিতে হাইফেন রয়েছে যা এগুলি কী হিসাবে অকেজো করে তোলে।
altocumulus

অবশেষে, আমি এই একটি সমাধান পাওয়া উত্তর কম্পাইলার যে এই একটি স্ট্রিং enum ছিল না বিশ্বাসী দ্বারা। আপনার নিজের উত্তরে এই তথ্যটি সম্পাদনা করার উপযুক্ত হতে পারে।
altocumulus

6

এনাম মানগুলি কীভাবে লুপ করবেন (আমার বেশ কয়েকটি এনামের প্রচুর পরিমাণ পরীক্ষা করার পদ্ধতিটি পরীক্ষা করা হয়েছিল) তা আমার জানা দরকার এবং আমি এটি ভালভাবে কাজ করতে দেখতে পেলাম:

export enum Environment {
    Prod = "http://asdf.com",
    Stage = "http://asdf1234.com",
    Test = "http://asdfasdf.example.com"
}

Object.keys(Environment).forEach((environmentKeyValue) => {
    const env = Environment[environmentKeyValue as keyof typeof Environment]
    // env is now equivalent to Environment.Prod, Environment.Stage, or Environment.Test
}

সূত্র: https://blog.mikeski.net/de વિકાસ ment / javascript / typescript- enums- to- from- string/


এই উত্তর জেনিয়াস! এটা ভাল। বিশেষত যেভাবে আপনি স্ট্রিংটি থেকে এনাম তৈরি করেন। এনামগুলি বা অন্যান্য ক্ষেত্রে পরীক্ষা করার সময় এটি আপনাকে এত বেশি টাইপ করতে পারে।
ফ্লোরিয়ান লেটজেব

হ্যাঁ, আমি এটি জেস্টের সাথে eachপ্রতিটি একক
এনাম কেসকে

6

আমি কোন উত্তর যে পেতে পারেন খুঁজছেন ছিল enumএকটি থেকে string, কিন্তু আমার ক্ষেত্রে, enums মান আলাদা স্ট্রিং মান সহযোগীর ছিল। ওপিতে একটি সহজ এনাম Colorছিল তবে আমার কিছু আলাদা ছিল:

enum Gender {
  Male = 'Male',
  Female = 'Female',
  Other = 'Other',
  CantTell = "Can't tell"
}

আপনি যখন স্ট্রিং Gender.CantTellদিয়ে সমাধান করার চেষ্টা করবেন "Can't tell", এটি undefinedআসল উত্তর দিয়ে ফিরে আসবে ।

আর একটি উত্তর

মূলত, আমি এই উত্তর থেকে দৃ strongly়ভাবে অনুপ্রাণিত হয়ে অন্য একটি উত্তর নিয়ে এসেছি :

export const stringToEnumValue = <ET, T>(enumObj: ET, str: string): T =>
  (enumObj as any)[Object.keys(enumObj).filter(k => (enumObj as any)[k] === str)[0]];

মন্তব্য

  • আমরা নিতে প্রথম ফলাফলের এর filterঅভিমানী ক্লায়েন্ট enum থেকে একটি বৈধ স্ট্রিং ক্ষণস্থায়ী হয়। যদি এটি না হয় তবে undefinedফিরে আসবে।
  • আমরা নিক্ষেপ enumObjকরার anyকারণ সঙ্গে টাইপ করা বিষয় 3.0+ (বর্তমানে টাইপ করা বিষয় 3.5 ব্যবহার করে), enumObjযেমন সমাধান করা unknown

ব্যবহারের উদাহরণ

const cantTellStr = "Can't tell";

const cantTellEnumValue = stringToEnumValue<typeof Gender, Gender>(Gender, cantTellStr);
console.log(cantTellEnumValue); // Can't tell

দ্রষ্টব্য: এবং কেউ যেমন একটি মন্তব্যে উল্লেখ করেছেন, আমিও এটি ব্যবহার করতে চেয়েছিলাম noImplicitAny

নতুন সংস্করণ

কোনও cast anyালাই এবং সঠিক টাইপিং নেই।

export const stringToEnumValue = <T, K extends keyof T>(enumObj: T, value: string): T[keyof T] | undefined =>
  enumObj[Object.keys(enumObj).filter((k) => enumObj[k as K].toString() === value)[0] as keyof typeof enumObj];

এছাড়াও, আপডেট করা সংস্করণটিকে এটি কল করার একটি সহজ উপায় রয়েছে এবং এটি আরও পঠনযোগ্য:

stringToEnumValue(Gender, "Can't tell");

3

Enum

enum MyEnum {
    First,
    Second,
    Three
}

নমুনা ব্যবহার

const parsed = Parser.parseEnum('FiRsT', MyEnum);
// parsed = MyEnum.First 

const parsedInvalid= Parser.parseEnum('other', MyEnum);
// parsedInvalid = undefined

কেস সেনসিটিভ পার্স উপেক্ষা করুন

class Parser {
    public static parseEnum<T>(value: string, enumType: T): T[keyof T] | undefined {
        if (!value) {
            return undefined;
        }

        for (const property in enumType) {
            const enumMember = enumType[property];
            if (typeof enumMember === 'string') {
                if (enumMember.toUpperCase() === value.toUpperCase()) {
                    const key = enumMember as string as keyof typeof enumType;
                    return enumType[key];
                }
            }
        }
        return undefined;
    }
}

return enumType[property];আপনার Skills = "anyvalue"
এনাম

@ neustart47 আপনি দয়া করে প্রশ্ন জিজ্ঞাসা করতে পারেন?
: Дармаев

এটা কোন প্রশ্ন নয়। আমি কেবল আমার মতো একই কেসটি অনুসন্ধান করছে এমন কারও জন্য কিছু পরিবর্তন উল্লেখ করেছি। আপনার উত্তরটি সঠিক।
neustart47

2

আপনি যেভাবে তৈরি করেছেন এনামগুলি এমন একটি বস্তুতে সংকলিত হয় যা উভয়কে সামনে (name -> value)এবং বিপরীত (value -> name)ম্যাপিংগুলি সঞ্চয় করে । যেহেতু আমরা এই ক্রোম ডেভোলস স্ক্রিনশট থেকে পর্যবেক্ষণ করতে পারি:

এখানে চিত্র বর্ণনা লিখুন

দ্বৈত ম্যাপিং কীভাবে কাজ করে এবং কীভাবে একে অপরকে কাস্ট করা যায় তার একটি উদাহরণ এখানে রয়েছে:

enum Color{
    Red, Green
}
// To Number
var greenNr: number = Color['Green'];
console.log(greenNr); // logs 1

// To String
var greenString: string = Color[Color['Green']];  // or Color[Color[1]
console.log(greenString); // logs Green

// In your example

// recieve as Color.green instead of the string green
var green: string = Color[Color.Green];  

// obtain the enum number value which corresponds to the Color.green property
var color: Color = (<any>Color)[green];  

console.log(color); // logs 1

1

এটা চেষ্টা কর

বর্ণের রঙ: রঙ = (যে কোনও হিসাবে রঙ) ["সবুজ];

এটি 3.5.3 সংস্করণে দুর্দান্ত কাজ করে


0

আপনি যদি নিজের এনমের কার্যকারিতা বাড়ানোর জন্য নেমস্পেস ব্যবহার করেন তবে আপনিও এর মতো কিছু করতে পারেন

    enum Color {
        Red, Green
    }

    export namespace Color {
      export function getInstance(color: string) : Color {
        if(color == 'Red') {
          return Color.Red;
        } else if (color == 'Green') {
          return Color.Green;
        }
      }
    }

এবং এটি এটি ব্যবহার করুন

  Color.getInstance('Red');
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.