परिचय: JavaScript को Generics की आवश्यकता क्यों है?
\n\nJavaScript (विशेषकर Node.js वातावरण में) में विकास अक्सर कोड दोहराव की समस्या का सामना करता है। कल्पना करें कि आपको एक ऐसा फ़ंक्शन लिखना है जो संख्याओं, स्ट्रिंग्स और ऐरे के साथ काम करता हो। Generics (जेनेरिक्स) के बिना, आप या तो कई ओवरलोड लिखते हैं या any का उपयोग करते हैं, जिससे टाइप की सारी जादू खत्म हो जाती है।
Generics एक ऐसा तंत्र है जो आपको ऐसे घटक (फ़ंक्शन, क्लास, इंटरफ़ेस) बनाने की अनुमति देता है जो विभिन्न डेटा प्रकारों के साथ काम करते हैं, साथ ही सख्त टाइपिंग बनाए रखते हैं। JavaScript के संदर्भ में, जेनेरिक्स पूरी तरह से TypeScript के माध्यम से उपलब्ध हैं, लेकिन उनके सिद्धांतों को समझना किसी भी आधुनिक डेवलपर के लिए महत्वपूर्ण है।
\n\nइस लेख में, हम समझेंगे कि generics की आवश्यकता क्यों है, Node.js में व्यवहार में उनका उपयोग कैसे करें, और यह आपके कोड को अधिक सुरक्षित और पुन: प्रयोज्य क्यों बनाता है।
\n\n1. TypeScript में Generics: टाइप सुरक्षा का आधार
\n\nहालाँकि शुद्ध JavaScript में जेनेरिक्स का अंतर्निहित समर्थन नहीं है, TypeScript (JS पर एक ओवरले) उन्हें पूरी तरह से प्रदान करता है। यही कारण है कि Node.js (NestJS, Express टाइप्स के साथ) के सभी आधुनिक फ्रेमवर्क और लाइब्रेरी सक्रिय रूप से उनका उपयोग करते हैं।
\n\nसरल उदाहरण: identity फ़ंक्शन
\n\nक्लासिक उदाहरण एक ऐसा फ़ंक्शन है जो वही लौटाता है जो उसे मिला:
\n\n// बिना generics के — any का उपयोग (टाइप खो देते हैं)\nfunction identity(arg: any): any {\n return arg;\n}\n\n// generic के साथ — टाइप संरक्षित रहता है\nfunction identity<T>(arg: T): T {\n return arg;\n}\n\n// उपयोग\nconst num = identity<number>(42); // टाइप: number\nconst str = identity<string>('hello'); // टाइप: string\n\n\nध्यान दें: <T> एक टाइप पैरामीटर है। हम TypeScript से कह रहे हैं: "टाइप बाद में दिया जाएगा"। कंपाइलर स्वचालित रूप से टाइप का अनुमान लगाता है, इसलिए अक्सर आप बस identity(42) लिख सकते हैं।
यह Node.js के लिए क्यों महत्वपूर्ण है?
\n\nNode.js में, आप लगातार API, डेटाबेस और बाहरी सेवाओं के साथ काम करते हैं। Generics यह सुनिश्चित करने में मदद करते हैं कि डेटा ठीक उसी प्रारूप में आता है जिसकी आप अपेक्षा करते हैं:
\n\n// API के साथ काम करने के लिए फ़ंक्शन\nasync function fetchData<T>(url: string): Promise<T> {\n const response = await fetch(url);\n return response.json() as Promise<T>;\n}\n\n// अब हम रिस्पॉन्स की सटीक संरचना जानते हैं\ninterface User {\n id: number;\n name: string;\n}\n\nconst user = await fetchData<User>('/api/user/1');\n// user.name — स्ट्रिंग, user.id — संख्या (TypeScript यह जाँचता है)\n\n\n2. व्यावहारिक परिदृश्य: ऐरे और कलेक्शन के साथ काम करना
\n\nGenerics विशेष रूप से ऐरे और डेटा कलेक्शन के साथ काम करते समय उपयोगी होते हैं। आइए Node.js से एक वास्तविक उदाहरण देखें — फ़िल्टरिंग और ट्रांसफ़ॉर्मेशन फ़ंक्शन।
\n\nमैपिंग के लिए Generic-फ़ंक्शन
\n\n// फ़ंक्शन एक प्रकार के ऐरे को दूसरे प्रकार के ऐरे में बदलता है\nfunction mapArray<T, U>(items: T[], mapper: (item: T) => U): U[] {\n return items.map(mapper);\n}\n\n// उदाहरण: User से केवल नाम प्राप्त करना\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nconst users: User[] = [\n { id: 1, name: 'Alice', email: 'alice@example.com' },\n { id: 2, name: 'Bob', email: 'bob@example.com' }\n];\n\nconst names: string[] = mapArray(users, (user) => user.name);\n// names: ['Alice', 'Bob'] — टाइप string[] गारंटीकृत\n\n\nयहाँ <T, U> दो टाइप पैरामीटर हैं। T इनपुट ऐरे का टाइप है, U परिणाम का टाइप है। यह टाइप खोए बिना अधिकतम लचीलापन देता है।
स्टैक के लिए Generic-क्लास
\n\nNode.js में अक्सर डेटा संरचनाओं की आवश्यकता होती है। आइए एक टाइप-सुरक्षित स्टैक बनाएँ:
\n\nclass Stack<T> {\n private items: T[] = [];\n\n pu