परिचय: लेगेसी कोड को TypeScript में विशेष दृष्टिकोण की आवश्यकता क्यों है
\nविरासत (लेगेसी) कोड के साथ काम करना किसी भी डेवलपर के लिए एक अपरिहार्य वास्तविकता है, विशेष रूप से बड़ी परियोजनाओं में। अक्सर ऐसा कोड सख्त टाइपिंग के बिना, हर कोने में any का उपयोग करके लिखा जाता है, और निर्भरताओं का एक उलझा हुआ जाल प्रस्तुत करता है। यहाँ सरल रिफैक्टरिंग काम नहीं करती - एक व्यवस्थित, उन्नत दृष्टिकोण की आवश्यकता है।
इस लेख में, हम TypeScript में लेगेसी कोड के रिफैक्टरिंग की उन रणनीतियों पर विचार करेंगे जो बुनियादी गाइडों से परे हैं। आप सीखेंगे कि कैसे सुरक्षित रूप से सख्त टाइपिंग शुरू करें, पैटर्न की मदद से बदलावों को अलग करें, और नियमित कार्यों को स्वचालित करने के लिए कंपाइलर की क्षमताओं का उपयोग करें।
\n\nरणनीति 1: "टाइप ब्रिज" के माध्यम से क्रमिक रूप से सख्त टाइपिंग शुरू करना
\nलेगेसी कोड की मुख्य समस्याओं में से एक है any का पूर्ण उपयोग। एक बार में सभी any को विशिष्ट प्रकारों से बदलने का प्रयास सैकड़ों त्रुटियों और विकास के पक्षाघात का कारण बनेगा। इसके बजाय, हम "टाइप ब्रिज" तकनीक का उपयोग करते हैं।
विधि का सार: हम पूरे मॉड्यूल को एक साथ फिर से नहीं लिखते हैं, बल्कि मध्यवर्ती ब्रिज प्रकार बनाते हैं जो धीरे-धीरे any को विस्थापित करते हैं।
उदाहरण: "ग्रे" मॉड्यूल की टाइपिंग
\nमान लीजिए, हमारे पास उपयोगकर्ताओं के साथ काम करने के लिए एक पुराना मॉड्यूल है:
\n// legacyModule.ts\nexport function processUser(data: any): any {\n // ... बहुत सारा अपठनीय कोड\n return { id: data.id, name: data.name, age: data.age };\n}\nपूरे फंक्शन को तुरंत टाइप करने के बजाय, हम UserData और User बनाते हैं:
// types.ts\nexport interface UserData {\n id: number;\n name: string;\n age?: number; // फ़ील्ड अनुपस्थित हो सकता है\n}\n\nexport interface User {\n id: number;\n fullName: string;\n isAdult: boolean;\n}\nअब हम इन प्रकारों का उपयोग करते हैं, लेकिन पिछड़ी संगतता के लिए पुराने सिग्नेचर को छोड़ देते हैं:
\n// legacyModule.ts (रिफैक्टरिंग चरण 1)\nimport { UserData, User } from './types';\n\nexport function processUser(data: UserData): User {\n const isAdult = data.age ? data.age >= 18 : false;\n return {\n id: data.id,\n fullName: data.name,\n isAdult,\n };\n}\n\n// संगतता के लिए पुराना सिग्नेचर\nexport function processUserLegacy(data: any): any {\n return processUser(data as UserData);\n}\nसभी उपभोक्ताओं के नए फंक्शन पर स्विच करने के बाद, हम processUserLegacy को हटा देते हैं। यह दृष्टिकोण निर्भरताओं के टूटने के जोखिम को कम करता है।
रणनीति 2: "एडेप्टर" पैटर्न के साथ "गंदी" निर्भरताओं को अलग करना
\nलेगेसी कोड अक्सर बाहरी लाइब्रेरी, वैश्विक स्थितियों या पुराने API से निकटता से जुड़ा होता है। सुरक्षित रूप से रिफैक्टरिंग करने के लिए, इन निर्भरताओं को अलग करना आवश्यक है। इसके लिए सबसे अच्छा उपकरण इंटरफेस के साथ संयुक्त "एडेप्टर" पैटर्न है।
\n\nउदाहरण: पुराने API को अलग करना
\n// oldApi.ts (लेगेसी)\nexport function fetchOldData(callback: (data: any) => void): void {\n // कॉलबैक के साथ पुराना API\n setTimeout(() => callback({ value: 42 }), 100);\n}\nहम नए दृष्टिकोण (Promise-आधारित) और एडेप्टर के लिए एक इंटरफ़ेस बनाते हैं:
\n// apiAdapter.ts\nimport { fetchOldData } from './oldApi';\n\nexport interface IDataFetcher {\n fetchData(): Promise<{ value: number }>;\n}\n\nexport class LegacyApiAdapter implements IDataFetcher {\n fetchData(): Promise<{ value: number }> {\n return new Promise((resolve, reject) => {\n fetchOldData((data) => {\n if (data) {\n resolve(data);\n } else {\n reject(new Error('No data'));\n }\n });\n });\n }\n}\nअब सभी नया कोड IDataFetcher का उपयोग करता है। जब आप पुराने API को पूरी तरह से फिर से लिख देंगे, तो आपको बाकी कोड को छुए बिना केवल एडेप्टर के कार्यान्वयन को बदलना होगा। यह प्रतिगमन के जोखिम को न्यूनतम कर देता है।