परिचय: window में प्रॉपर्टी जोड़ना हर TypeScript डेवलपर के लिए सिरदर्द क्यों है?
\n\nएक स्थिति की कल्पना करें: आप TypeScript में एक आधुनिक SPA एप्लिकेशन लिख रहे हैं। सब कुछ सुचारू रूप से चल रहा है, जब तक कि ग्लोबल स्टेट या बाहरी स्क्रिप्ट (जैसे, एनालिटिक्स, मैप्स या पेमेंट गेटवे) के साथ एकीकरण को सहेजने की आवश्यकता न हो। आप लिखते हैं:
\n\nwindow.myAppConfig = { apiKey: '123' };\n\nऔर तब TypeScript आपको एक लाल त्रुटि दिखाता है: "Property 'myAppConfig' does not exist on type 'Window & typeof globalThis'"। परिचित लगता है? इस प्रश्न ने Stack Overflow पर हज़ारों व्यूज़ एकत्र किए हैं, और आज हम न केवल एक तैयार समाधान देंगे, बल्कि TypeScript के अंदर झाँकेंगे, ताकि यह समझ सकें कि ऐसा क्यों होता है और इससे सुरुचिपूर्ण और सुरक्षित तरीके से कैसे निपटा जाए।
\n\nइस लेख में, हम कई दृष्टिकोणों पर चर्चा करेंगे - शुरुआती लोगों के लिए 'अस्थायी समाधान' से लेकर पेशेवर पैटर्न तक जो senior डेवलपर्स उपयोग करते हैं। चलिए शुरू करते हैं!
\n\nअंदर की बात: TypeScript window.myProp पर क्यों आपत्ति करता है?
\n\nसमस्या को समझने के लिए, यह याद रखना होगा कि TypeScript JavaScript के ऊपर एक परत है जो स्टैटिक टाइपिंग जोड़ती है। ब्राउज़र में window ऑब्जेक्ट एक ग्लोबल ऑब्जेक्ट है जिसका पूर्वनिर्धारित प्रकार (Window) होता है। यह प्रकार TypeScript की मानक लाइब्रेरी (lib.dom.d.ts) में वर्णित है और इसमें सभी मानक प्रॉपर्टी शामिल हैं: document, location, setTimeout और सैकड़ों अन्य।
जब आप window.myProp असाइन करने का प्रयास करते हैं, TypeScript जाँचता है: 'क्या Window इंटरफ़ेस में ऐसी कोई प्रॉपर्टी है?' नहीं - तो यह एक त्रुटि है। यह टाइपो और ग्लोबल स्कोप के आकस्मिक प्रदूषण से सुरक्षा है। लेकिन क्या होगा यदि आप जानबूझकर window का विस्तार करना चाहते हैं?
विधि 1: सबसे सरल, लेकिन खतरनाक — as any
\n\nपहला विकल्प जो एक नौसिखिए के दिमाग में आता है - टाइप कास्टिंग का उपयोग करके TypeScript को 'चुप' कराना:
\n\n(window as any).myAppConfig = { apiKey: '123' };\n\nलाभ: तेज़, काम करता है, अतिरिक्त परिभाषाओं की आवश्यकता नहीं है।
\nनुकसान: आप TypeScript के सभी लाभ खो देते हैं। कोई ऑटो-सुझाव नहीं, कोई टाइप जाँच नहीं। यदि आप गलती से myAppConfigg लिखते हैं - कोई त्रुटि नहीं होगी, लेकिन एप्लिकेशन रनटाइम पर क्रैश हो जाएगा। यह कार में एयरबैग बंद करने जैसा है - चलाया जा सकता है, लेकिन जोखिम भरा।
कब उपयोग करें: केवल त्वरित प्रोटोटाइपिंग के लिए या यदि आप सुनिश्चित हैं कि प्रॉपर्टी का उपयोग केवल एक बार किया जाएगा और हटा दिया जाएगा।
\n\nविधि 2: ग्लोबल इंटरफ़ेस का विस्तार (Interface Merging)
\n\nTypeScript इंटरफ़ेस मर्जिंग (declaration merging) का समर्थन करता है। यह एक महत्वपूर्ण तंत्र है जो मौजूदा Window प्रकार में नई प्रॉपर्टी 'जोड़ने' की अनुमति देता है। इसके लिए, ग्लोबल स्कोप में उसी नाम के साथ एक इंटरफ़ेस घोषित करना होगा।
एक फ़ाइल global.d.ts बनाएँ (या अपने प्रोजेक्ट की किसी भी .d.ts फ़ाइल में जोड़ें):
// global.d.ts\ninterface Window {\n myAppConfig: {\n apiKey: string;\n debugMode?: boolean;\n };\n myAnalyticsFunction: (event: string, data: object) => void;\n}\n\nअब आप लिख सकते हैं:
\n\nwindow.myAppConfig = { apiKey: '123' };\nwindow.myAnalyticsFunction('page_view', { page: '/home' });\n\n// TypeScript बताएगा कि apiKey एक string है\nconsole.log(window.myAppConfig.apiKey); // ✅ बिना त्रुटि के\n\nयह अंदरूनी रूप से कैसे काम करता है? TypeScript स्वचालित रूप से समान नाम वाले सभी इंटरफ़ेस घोषणाओं को मर्ज (merge) करता है। यदि lib.dom.d.ts में पहले से interface Window { ... } मौजूद है, तो उसी नाम वाला आपका इंटरफ़ेस बस उसमें नई प्रॉपर्टी जोड़ देगा। इसे glob कहा जाता है।