"गलत setTimeout": कैसे TypeScript डेवलपर्स को पागल कर देता है
\nक्या आपने कभी TypeScript पर एक सरल टाइमर लिखा है, और कोड एडिटर अचानक सब कुछ लाल रंग में रेखांकित करने लगा? परिचित दृश्य: आप setTimeout आयात करते हैं, const timer = setTimeout(...) लिखते हैं, और TypeScript एक त्रुटि देता है या एक समझ से बाहर का प्रकार सुझाता है। मामला क्या है? पता चला, setTimeout के दो संस्करण हैं - एक ब्राउज़र (window) के लिए, दूसरा सर्वर (Node.js) के लिए। और TypeScript, एक पूर्णतावादी होने के नाते, हमें चुनने के लिए मजबूर करता है।
यह विषय Stack Overflow पर सबसे लोकप्रिय में से एक है। हजारों डेवलपर्स एक ही गलती पर ठोकर खाते हैं। लेकिन हम केवल उत्तर कॉपी नहीं करेंगे। हम समस्या की जड़ को समझेंगे, समझेंगे कि टाइपिंग कैसे काम करती है, और ऐसा कोड लिखना सीखेंगे जो न तो ब्राउज़र में और न ही Node.js में टूटेगा।
\n\nsetTimeout के दो संस्करण क्यों?
\nऐतिहासिक रूप से, JavaScript दो दुनियाओं में रहता है: क्लाइंट (ब्राउज़र) और सर्वर (Node.js)। ब्राउज़र में, setTimeout ग्लोबल ऑब्जेक्ट window की एक विधि है। Node.js में, यह ग्लोबल मॉड्यूल timers का एक फंक्शन है। वे एक ही काम करते हैं, लेकिन उनके प्रकार हस्ताक्षर अलग हैं।
यहाँ मुख्य अंतर हैं:
\n- \n
- वापसी मान: ब्राउज़र में
window.setTimeoutएकnumber(टाइमर पहचानकर्ता) लौटाता है। Node.js में - एकNodeJS.Timeoutऑब्जेक्ट। \n - संदर्भ: ब्राउज़र में कॉलबैक के अंदर
this(गैर-सख्त मोड में)windowहै। Node.js में - टाइमर ऑब्जेक्ट। \n - टाइपिंग: TypeScript विभिन्न वातावरणों के लिए अलग-अलग घोषणाएँ प्रदान करता है। यदि आप सार्वभौमिक कोड (आइसोमॉर्फिक एप्लिकेशन) लिखते हैं, तो संघर्ष उत्पन्न होता है। \n
कोड में समस्या कैसी दिखती है
\nकल्पना करें कि आप एक लाइब्रेरी विकसित कर रहे हैं जो क्लाइंट और सर्वर दोनों पर काम करनी चाहिए। आप ऐसा कोड लिखते हैं:
\n// utils.ts\nexport function delay(ms: number): Promise<void> {\n return new Promise(resolve => {\n const timer = setTimeout(resolve, ms);\n // timer का प्रकार क्या है? number या NodeJS.Timeout?\n });\n}\nTypeScript देखेगा कि setTimeout दो प्रकार का हो सकता है, और एक त्रुटि देगा: "Type 'Timeout' is not assignable to type 'number'." या इसके विपरीत, tsconfig.json सेटिंग्स और कनेक्टेड प्रकारों पर निर्भर करता है।
इसे और स्पष्ट करने के लिए, यहाँ बताया गया है कि यदि आप उन्हें ReturnType के माध्यम से देखते हैं तो प्रकार कैसे दिखते हैं:
// ब्राउज़र में (lib.dom.d.ts)\ntype BrowserTimer = ReturnType<typeof window.setTimeout>; // number\n\n// Node.js में (@types/node)\ntype NodeTimer = ReturnType<typeof setTimeout>; // NodeJS.Timeout\n\nविभिन्न परिदृश्यों के लिए सही समाधान
\nआइए चार दृष्टिकोणों पर विचार करें। वह चुनें जो आपके प्रोजेक्ट के लिए उपयुक्त हो।
\n\n1. यदि आप केवल ब्राउज़र के लिए लिख रहे हैं
\nसबसे सरल मामला। बस number प्रकार निर्दिष्ट करें और स्पष्ट रूप से window.setTimeout का उपयोग करें:
// browser-timer.ts\nconst timerId: number = window.setTimeout(() => {\n console.log('एक सेकंड बीत गया');\n}, 1000);\n\n// साफ करने के लिए\nwindow.clearTimeout(timerId);\nयह क्यों काम करता है? ब्राउज़र वातावरण में, window.setTimeout हमेशा एक संख्या लौटाता है। TypeScript यह जानता है यदि आपने lib: ["dom"] कनेक्ट किया है।
2. यदि आप केवल Node.js के लिए लिख रहे हैं
\nयहाँ प्रकार NodeJS.Timeout है। इसका सीधे उपयोग करें:
// node-timer.ts\nimport { setTimeout } from 'timers'; // स्पष्टता के लिए स्पष्ट आयात\n\nconst timer: NodeJS.Timeout = setTimeout(() => {\n console.log('टाइमर चालू हुआ');\n}, 2000);\n\nclearTimeout(timer); // clearTimeout NodeJS.Timeout स्वीकार करता है\nमहत्वपूर्ण: Node.js में, clearTimeout भी No