TypeScript में ऑब्जेक्ट को डायनामिक रूप से गुण कैसे असाइन करें? शुरुआती लोगों के लिए सरल विश्लेषण
\n\nनमस्ते, दोस्त! यदि आपने कभी JavaScript में लिखा है और फिर TypeScript पर आए हैं, तो आपने निश्चित रूप से ऐसी स्थिति का सामना किया होगा जहाँ आपको किसी ऑब्जेक्ट में तुरंत एक नया गुण जोड़ने की आवश्यकता होती है। JS में यह बहुत आसान है: obj.newProp = 'value'। लेकिन जैसे ही आप TypeScript में भी ऐसा ही करने की कोशिश करते हैं, कंपाइलर शिकायत करने लगता है: "Property 'newProp' does not exist on type ..."। परिचित लगता है?
चिंता न करें, यह सामान्य है। TypeScript हमें आकस्मिक त्रुटियों से बचाता है, लेकिन कभी-कभी इसकी सख्ती अनावश्यक लगती है। इस लेख में, हम समझेंगे कि ऑब्जेक्ट्स को डायनामिक रूप से सही और सुरक्षित तरीके से गुण कैसे असाइन करें। आप कई सिद्ध तरीके सीखेंगे - सरल से लेकर अधिक सुंदर तक। चलिए शुरू करते हैं!
\n\nTypeScript शिकायत क्यों करता है?
\n\nसमस्या को हल करने से पहले, आइए इसकी जड़ को समझें। TypeScript JavaScript के ऊपर एक ओवरले है जो स्टैटिक टाइपिंग जोड़ता है। जब आप एक ऑब्जेक्ट घोषित करते हैं:
\n\nconst user = { name: 'अन्ना', age: 25 };\n\n\nTypeScript स्वचालित रूप से इसका प्रकार निकालता है: { name: string; age: number }। इसका मतलब है कि ऑब्जेक्ट user में केवल ये दो गुण हो सकते हैं। email जोड़ने का प्रयास कंपाइलेशन त्रुटि उत्पन्न करेगा:
user.email = 'anna@example.com'; // ❌ त्रुटि!\n\n\nTypeScript नहीं जानता कि ऐसा गुण प्रकट हो सकता है, और कोड को ब्लॉक कर देता है। लेकिन वास्तविक जीवन में, अक्सर गुणों को डायनामिक रूप से जोड़ने की आवश्यकता होती है - उदाहरण के लिए, API या फॉर्म से डेटा के साथ काम करते समय। आइए देखें कि इसे सही तरीके से कैसे किया जाए।
\n\nविधि 1: सबसे सरल — as any
\n\nतेज़ लेकिन गंदा तरीका as any का उपयोग करना है। यह सचमुच TypeScript से कहता है: "इस ऑब्जेक्ट के लिए प्रकार जाँच बंद करें"।
const user: any = { name: 'अन्ना', age: 25 };\nuser.email = 'anna@example.com'; // ✅ काम करता है\nuser.isAdmin = true; // ✅ काम करता है\n\n\nयह बुरा क्यों है? क्योंकि आप TypeScript के सभी लाभ खो देते हैं: ऑटो-कम्प्लीशन, टाइप चेकिंग, टाइपो से सुरक्षा। यदि गलती से user.emial लिखते हैं, तो कोई त्रुटि नहीं होगी - आपको इसके बारे में केवल रनटाइम पर पता चलेगा। इस विधि का उपयोग केवल त्वरित प्रोटोटाइपिंग के लिए या जब आपको पूरी तरह से पता हो कि आप क्या कर रहे हैं, करें।
विधि 2: इंडेक्स सिग्नेचर (Index Signature)
\n\nअधिक सही दृष्टिकोण यह है कि पहले से घोषित करें कि ऑब्जेक्ट में डायनामिक गुण हो सकते हैं। इसके लिए इंडेक्स सिग्नेचर का उपयोग किया जाता है।
\n\ninterface User {\n name: string;\n age: number;\n [key: string]: any; // 👈 किसी भी अतिरिक्त गुण की अनुमति दें\n}\n\nconst user: User = { name: 'अन्ना', age: 25 };\nuser.email = 'anna@example.com'; // ✅ काम करता है\nuser.phone = '+7-999-123-45-67'; // ✅ काम करता है\n\n\nयहाँ क्या हो रहा है? [key: string]: any का अर्थ है: "ऑब्जेक्ट में कोई भी स्ट्रिंग कुंजी हो सकती है, और उनके मान किसी भी प्रकार के हो सकते हैं"। अब आप डायनामिक रूप से गुण जोड़ सकते हैं, और TypeScript शिकायत नहीं करेगा।
महत्वपूर्ण बारीकी: यदि आप मानों के प्रकारों को सीमित करना चाहते हैं, तो any को एक विशिष्ट प्रकार से बदलें:
interface User {\n name: string;\n age: number;\n [key: string]: string | number; // केवल स्ट्रिंग और संख्याएँ\n}\n\n\nइंडेक्स सिग्नेचर एक उत्कृष्ट विकल्प है जब आप पहले से जानते हैं कि ऑब्जेक्ट का विस्तार होगा। लेकिन सावधान रहें: यदि इंटरफ़ेस में अन्य प्रकारों के साथ अन्य गुण हैं, तो उन्हें भी सिग्नेचर का पालन करना होगा।
\n\nविधि 3: उपयोगिता प्रकार Record
\n\nयदि आपको एक ऐसा ऑब्जेक्ट बनाने की आवश्यकता है जहाँ सभी कुंजियाँ और मान एक ही प्रकार के हों, तो अंतर्निहित प्रकार Record<Keys, Type> का उपयोग करें। यह शब्दकोशों या मैपिंग के लिए एकदम सही है।
type UserRoles = Record<string, 'admin' | 'user' | 'guest'>;\n\nconst roles: UserRoles = {\n anna: 'admin',\n ivan: 'user',\n};\