परिचय: esModuleInterop केवल tsconfig में एक टिक नहीं है
\n\nयदि आपने कभी TypeScript में लिखा है और express या lodash जैसी लाइब्रेरी को इम्पोर्ट किया है, तो आपने निश्चित रूप से उस क्षण का सामना किया होगा जब कंपाइलर import * as express from 'express' पर त्रुटि देता है। या, इसके विपरीत, आप शांति से import express from 'express' का उपयोग करते हैं, लेकिन जनरेटेड JavaScript कोड में आपको एक अजीब संरचना module.exports.default दिखाई देती है। यह क्या जादू है? और जादू (या इसकी कमी) आपके tsconfig.json में esModuleInterop फ्लैग है।
यह पैरामीटर Stack Overflow पर सबसे लोकप्रिय प्रश्नों में से एक है (हजारों व्यूज!), और यह आश्चर्य की बात नहीं है: इसकी समझ के बिना मॉड्यूल असंगति के जाल में फंसना आसान है। इस ट्यूटोरियल में हम केवल सिद्धांत नहीं समझाएंगे, बल्कि लाइव उदाहरणों के साथ समस्या से समाधान तक का सफर तय करेंगे। चलिए शुरू करते हैं!
\n\nसमस्या: दो मॉड्यूल दुनियाओं का संघर्ष
\n\nTypeScript JavaScript के ऊपर एक ओवरले है, और JavaScript में ऐतिहासिक रूप से दो मुख्य मॉड्यूल सिस्टम हैं:
\n- \n
- CommonJS (CJS) — Node.js का मानक,
require()औरmodule.exportsका उपयोग करता है। उदाहरण:const express = require('express');\n - ES Modules (ESM) — आधुनिक मानक,
importऔरexportका उपयोग करता है। उदाहरण:import express from 'express';\n
समस्या यह है कि ये सिस्टम डिफ़ॉल्ट एक्सपोर्ट (default export) को अलग-अलग तरीके से संभालते हैं। ESM में एक मॉड्यूल में एक export default हो सकता है, और इसे import name from 'module' के रूप में इम्पोर्ट किया जाता है। CommonJS में "डिफ़ॉल्ट एक्सपोर्ट" की कोई अवधारणा नहीं है — केवल module.exports ऑब्जेक्ट है, जो कुछ भी हो सकता है।
जब TypeScript आपके कोड को CommonJS में कंपाइल करता है (जो अक्सर Node.js के लिए आवश्यक होता है), तो उसे निर्णय लेना होता है: import x from 'y' को require() के रूप में कैसे प्रस्तुत किया जाए? esModuleInterop के बिना, TypeScript इसे शाब्दिक रूप से करता है: यह module.exports.default बनाता है, जो CommonJS के तहत लिखी गई लाइब्रेरी के इम्पोर्ट को तोड़ देता है।
esModuleInterop क्या है?
\n\nesModuleInterop tsconfig.json में एक फ्लैग है, जो CommonJS और ES Modules के बीच अतिरिक्त संगतता को सक्षम करता है। जब इसे true पर सेट किया जाता है, तो TypeScript एक सहायक कोड जनरेट करता है जो आपको CommonJS मॉड्यूल के लिए भी import foo from 'bar' लिखने की अनुमति देता है, भले ही उनमें default-एक्सपोर्ट न हो।
TypeScript 4.x और उससे ऊपर में डिफ़ॉल्ट रूप से यह फ्लैग true है (यदि आप --init का उपयोग करते हैं), लेकिन पुराने प्रोजेक्ट्स में इसे अक्सर बंद कर दिया जाता था। क्यों? क्योंकि यह इम्पोर्ट के व्यवहार को बदल देता है, और समझ के बिना यह बग का कारण बनता है।
यह tsconfig.json में कैसा दिखता है
\n{\n "compilerOptions": {\n "esModuleInterop": true,\n // अन्य सेटिंग्स...\n }\n}\n\n\nइस फ्लैग को सक्षम करने से allowSyntheticDefaultImports भी स्वचालित रूप से सक्षम हो जाता है, जो टाइप स्तर पर वास्तविक default-एक्सपोर्ट के बिना मॉड्यूल से डिफ़ॉल्ट इम्पोर्ट की अनुमति देता है।
चरण-दर-चरण ट्यूटोरियल: समस्या से समाधान तक
\n\nआइए एक वास्तविक उदाहरण पर स्थिति को समझें। मान लीजिए हमारे पास CommonJS पर एक सरल लाइब्रेरी है:
\n\n// myLib.js (CommonJS)\nmodule.exports = function greet(name) {\n return `Hello, ${name}!`;\n};\n\n\nहम इसे TypeScript प्रोजेक्ट में उपयोग करना चाहते हैं। एक फ़ाइल index.ts बनाएं:
// index.ts\nimport greet from './myLib';\nconsole.log(greet('World'));\n\n\nअब देखते हैं कि esModuleInterop की विभिन्न सेटिंग्स के साथ कंपाइलेशन पर क्या होता है।
चरण 1: esModuleInterop के बिना (false)
\n\n"esModuleInterop": false के साथ कंपाइलेशन चलाएं। TypeScript एक त्रुटि देगा:
Module '"myLib"' has no d