require(x) vs import x: TypeScript डेवलपर्स के लिए यह एक आम समस्या क्यों है
\n\nअगर आपने कभी TypeScript में कोड लिखा है और Cannot use import statement outside a module या require is not defined जैसी एरर देखी है, तो आप अकेले नहीं हैं। Stack Overflow पर "The difference between 'require(x)' and 'import x'" सवाल को हज़ारों बार देखा जा चुका है। यह कोई संयोग नहीं है: दो मॉड्यूल सिस्टम के बीच भ्रम एक ऐसा जाल है जिसमें अनुभवी डेवलपर भी फंस जाते हैं।
इस ट्यूटोरियल में हम सिर्फ अंतर नहीं बताएंगे। हम पूरी तरह से समझ से लेकर सही सिंटैक्स चुनने के आत्मविश्वास तक का सफर तय करेंगे। आप जानेंगे कि TypeScript आपके कोड को कैसे कंपाइल करता है, require आज भी क्यों जीवित है, और import का उपयोग कब करना चाहिए।
1. ऐतिहासिक संदर्भ: दो सिस्टम कहां से आए
\n\nअंतर समझने के लिए JavaScript के इतिहास में झांकना ज़रूरी है। शुरू में Node.js में कोई बिल्ट-इन मॉड्यूल सिस्टम नहीं था। डेवलपर्स ने CommonJS बनाया — require() के ज़रिए मॉड्यूल जोड़ने का एक सिंक्रोनस तरीका। यह सर्वर साइड पर काम करता है, लेकिन ब्राउज़र के लिए उपयुक्त नहीं था — वहां एसिंक्रोनस लोडिंग की ज़रूरत थी।
बाद में ES Modules (ESM) स्टैंडर्ड आया — ECMAScript का आधिकारिक मॉड्यूल सिंटैक्स। TypeScript, JS के ऊपर एक लेयर होने के नाते, दोनों विकल्पों को सपोर्ट करता है। लेकिन यहीं से भ्रम शुरू होता है: आप import लिखते हैं, और कंपाइलर इसे require में बदल देता है — या उल्टा।
2. सिंटैक्स: मुख्य अंतर
\n\nआइए देखें कि दोनों तरीके कैसे दिखते हैं।
\n\nCommonJS (require)
\n\n// पूरे मॉड्यूल को इम्पोर्ट करना\nconst fs = require('fs');\n\n// मॉड्यूल के कुछ हिस्से को इम्पोर्ट करना (डिस्ट्रक्चरिंग)\nconst { readFile, writeFile } = require('fs');\n\n// एक्सपोर्ट\nmodule.exports = { myFunction, myVariable };\nexports.myFunction = () => { ... };\n\nES Modules (import)
\n\n// पूरे मॉड्यूल को इम्पोर्ट करना\nimport fs from 'fs';\n\n// नामित एक्सपोर्ट को इम्पोर्ट करना\nimport { readFile, writeFile } from 'fs';\n\n// सब कुछ एक ऑब्जेक्ट के रूप में इम्पोर्ट करना\nimport * as fs from 'fs';\n\n// एक्सपोर्ट\nexport const myVariable = 42;\nexport function myFunction() { ... }\nexport default class MyClass { }\n\nपहली नज़र में अंतर सिर्फ सिंटैक्स का है। लेकिन गहराई में जाएं।
\n\n3. स्टैटिक बनाम डायनामिक इम्पोर्ट
\n\nयह मुख्य अंतर है जो आपके कोड के काम करने के तरीके को प्रभावित करता है।
\n\n- \n
require— डायनामिक है। आप इसे कहीं भी, किसी कंडीशन या फंक्शन के अंदर कॉल कर सकते हैं। मॉड्यूल कॉल के समय लोड होता है। \n import— स्टैटिक है। इम्पोर्ट कंपाइलेशन के समय, कोड एक्जीक्यूट होने से पहले हल हो जाते हैं। ये हमेशा फ़ाइल के टॉप लेवल पर होने चाहिए। \n
डायनामिक require का उदाहरण:
\n\nlet myModule;\nif (process.env.NODE_ENV === 'production') {\n myModule = require('./production-config');\n} else {\n myModule = require('./dev-config');\n}\n\nऐसा import के साथ नहीं होगा — सिंटैक्स एरर आएगा। लेकिन इसके लिए डायनामिक import() है (जो Promise रिटर्न करता है):
if (condition) {\n const module = await import('./some-module');\n module.doSomething();\n}\n\n4. TypeScript मॉड्यूल को कैसे कंपाइल करता है
\n\nयह सब tsconfig.json में module सेटिंग पर निर्भर करता है। मुख्य विकल्प ये हैं:
- \n
"module": "commonjs"— आपकाimportrequireमें बदल जाएगा। कोड बिना अतिरिक्त सेटिंग्स के Node.js में काम करेगा। \n "module": "esnext"—importजस का तस रहेगा। यह आधुनिक ब्राउज़र या बंडलर्स (Webpack, Vite) के लिए उपयुक्त है। \n "module": "node16"या"nodenext"— TypeScript खुद तय करेगा कि किस सिस्टम का उपयोग करना है।