TypeScript में Indexed Object के प्रकार को नियंत्रित करना सीखें

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

यह विषय Stack Overflow पर क्यों छाया हुआ है?

\n\n

अगर आपने कभी TypeScript में कोड लिखा है और एक ऐसा ऑब्जेक्ट बनाने की कोशिश की है जहां सभी मान एक ही प्रकार के हों, तो आप शायद इस समस्या से जूझ चुके हैं। Stack Overflow पर सवाल "Enforcing the type of the indexed members of a Typescript object" ने हज़ारों व्यूज़ बटोरे हैं — यह JavaScript से आने वाले डेवलपर्स के लिए एक क्लासिक "गड़बड़" है।

\n\n

सोचिए: आपके पास एक कैश डिक्शनरी, डायनामिक कीज़ वाला कॉन्फ़िगरेशन, या सिर्फ़ नंबरों की एक मैप है। आप चाहते हैं कि TypeScript यह सुनिश्चित करे कि ऑब्जेक्ट में हर मान एक स्ट्रिंग, नंबर या कोई जटिल प्रकार हो। लेकिन कंपाइलर गलतियों को अनदेखा क्यों कर देता है? परिचित लग रहा है?

\n\n

इस लेख में हम इस समस्या के सभी मुख्य समाधानों पर चर्चा करेंगे: सरल Index Signatures से लेकर उन्नत Mapped Types तक। आप जानेंगे कि कब कौन सा तरीका इस्तेमाल करना है और किन खतरों से बचना है।

\n\n

समस्या: डायनामिक कीज़ वाला ऑब्जेक्ट

\n\n

मान लीजिए, हम एक यूज़र प्रबंधन सिस्टम बना रहे हैं। हमारे पास एक ऑब्जेक्ट है जहां कीज़ यूज़र ID हैं और मान उनके नाम हैं:

\n\n
interface UserCache {\n  [userId: string]: string;\n}\n\nconst cache: UserCache = {\n  'user_1': 'Alice',\n  'user_2': 'Bob',\n  // 'user_3': 123; // गलती! यह स्ट्रिंग होना चाहिए\n};\n\ncache['user_4'] = 'Charlie'; // ठीक है\ncache['user_5'] = 42; // गलती! Type 'number' 'string' को असाइन नहीं हो सकता\n
\n\n

लगता है सब काम कर रहा है। लेकिन एक बारीकी है: Index Signature किसी भी स्ट्रिंग की को अनुमति देता है। अगर हम अनुमत कीज़ के सेट को सीमित करना चाहें तो?

\n\n

तरीका 1: Index Signature — क्लासिक तरीका

\n\n

Index Signature ऑब्जेक्ट के सभी मानों का प्रकार सेट करने का सबसे आसान तरीका है। सिंटैक्स:

\n\n
interface StringMap {\n  [key: string]: string;\n}\n\nconst map: StringMap = {\n  hello: 'world',\n  foo: 'bar',\n};\n
\n\n

फ़ायदे:

\n
    \n
  • सरलता और पढ़ने में आसानी
  • \n
  • किसी भी संख्या में कीज़ के साथ काम करता है
  • \n
\n\n

नुकसान:

\n
    \n
  • कीज़ के सेट को सीमित नहीं कर सकते
  • \n
  • सभी मान एक ही प्रकार (या union) के होने चाहिए
  • \n
  • undefined मानों के साथ काम नहीं करता (सावधानी ज़रूरी)
  • \n
\n\n

शुरुआती लोगों की आम गलती: ऐसे ऑब्जेक्ट में एक मेथड जोड़ने की कोशिश करना:

\n\n
interface BadMap {\n  [key: string]: string;\n  length: number; // गलती! 'number' 'string' को असाइन नहीं हो सकता\n}\n
\n\n

यह काम नहीं करेगा क्योंकि length सामान्य प्रकार का उल्लंघन करता है। अगर प्रकार मिलाने हैं, तो union या Mapped Types का उपयोग करें।

\n\n

तरीका 2: Record — बिल्ट-इन हेल्पर

\n\n

TypeScript एक बिल्ट-इन प्रकार Record<K, V> प्रदान करता है, जो वही काम करता है लेकिन अधिक संक्षिप्त सिंटैक्स के साथ:

\n\n
type StringRecord = Record<string, string>;\n\nconst config: StringRecord = {\n  apiUrl: 'https://api.example.com',\n  timeout: '5000', // ठीक है, स्ट्रिंग\n  // port: 8080, // गलती!\n};\n\n// कीज़ को सीमित किया जा सकता है:\ntype AllowedKeys = 'name' | 'email' | 'phone';\ntype UserRecord = Record<AllowedKeys, string>;\n\nconst user: UserRecord = {\n  name: 'Alice',\n  email: 'alice@example.com',\n  phone: '+1234567890',\n  // age: '30', // गलती! 'age' AllowedKeys में नहीं है\n};\n
\n\n

कब उपयोग करें:

\n
    \n
  • जब जल्दी से एक टाइपिफ़ाइड डिक्शनरी बनानी हो
  • \n
  • जब कीज़ एक विशिष्ट सेट (union) हों
  • \n
  • ज्ञात फ़ील्ड वाले कॉन्फ़िगरेशन के लिए
  • \n
\n\n

कमी: Record अलग-अलग कीज़ के लिए अलग-अलग प्रकार सेट नहीं कर सकता। इसके लिए Mapped Types का उपयोग करें।

\n\n

तरीका 3: Map — ES6 का विकल्प

\n\n

अगर आप JavaScript के Map का उपयोग कर रहे हैं, तो TypeScript इसे बखूबी टाइप करता है।

ब्लॉग

पुस्तक अनुशंसाएँ