परिचय: Generics क्या हैं और वे क्यों महत्वपूर्ण हैं?
\n\nTypeScript सीखते समय, आप जल्द ही ऐसी स्थिति का सामना करते हैं जहाँ आपको एक फ़ंक्शन या क्लास लिखने की आवश्यकता होती है जो विभिन्न डेटा प्रकारों के साथ काम कर सके। विशेष उपकरणों के बिना, आपको या तो प्रत्येक प्रकार के लिए कोड की नकल करनी होगी, या any का उपयोग करना होगा, जो सख्त टाइपिंग के सारे जादू को खत्म कर देता है। यहीं पर Generics (जेनेरिक्स या सामान्यीकरण) काम आते हैं।
Generics TypeScript का एक शक्तिशाली तंत्र है जो आपको ऐसे घटक (फ़ंक्शन, क्लास, इंटरफ़ेस) बनाने की अनुमति देता है जो विभिन्न प्रकारों के साथ काम करते हैं, साथ ही सख्त टाइपिंग बनाए रखते हैं। कल्पना करें कि आप एक सार्वभौमिक कंटेनर लिख रहे हैं जो सेब, किताबें और संख्याएँ स्टोर कर सकता है, लेकिन TypeScript को ठीक-ठीक पता है कि प्रत्येक विशिष्ट मामले में अंदर क्या है।
\n\nइस लेख में, हम समझेंगे कि Generics क्यों ज़रूरी हैं, उन्हें कैसे घोषित करें और वास्तविक प्रोजेक्ट्स में उपयोग करें। आप सीखेंगे कि अपने कोड को अधिक लचीला, सुरक्षित और पुन: प्रयोज्य कैसे बनाएं।
\n\nGenerics की मूल बातें: सिंटैक्स और पहला फ़ंक्शन
\n\nआइए एक सरल उदाहरण से शुरू करते हैं। मान लीजिए, हमें एक फ़ंक्शन चाहिए जो एक आर्गुमेंट ले और उसे वापस कर दे (identity function)। जेनेरिक्स के बिना, हम इसे ऐसे लिखेंगे:
\n\nfunction identity(arg: number): number {\n return arg;\n}\n\nलेकिन यह फ़ंक्शन केवल संख्याओं के साथ काम करता है। इसे सार्वभौमिक बनाने के लिए, हम any का उपयोग कर सकते हैं:
function identity(arg: any): any {\n return arg;\n}\n\nसमस्या यह है कि हम प्रकार के बारे में जानकारी खो देते हैं। TypeScript को नहीं पता होता कि वही प्रकार वापस आएगा जो पास किया गया था। यहाँ पर Generics काम आते हैं:
\n\nfunction identity<T>(arg: T): T {\n return arg;\n}\n\n// उपयोग:\nlet output1 = identity<string>("नमस्ते"); // प्रकार string\nlet output2 = identity<number>(42); // प्रकार number\n\nसिंटैक्स को समझते हैं:
\n- \n
<T>— यह प्रकार पैरामीटर है। आप कोई भी अक्षर उपयोग कर सकते हैं, लेकिन परंपरा के अनुसार अक्सरT(Type),U,Vका उपयोग किया जाता है। \n arg: T— आर्गुमेंट का प्रकारTहै। \n : Tकोष्ठक के बाद — फ़ंक्शनTप्रकार का मान लौटाता है। \n
अब TypeScript जानता है: यदि आपने एक स्ट्रिंग पास की, तो आउटपुट भी स्ट्रिंग होगी। यदि संख्या — संख्या। प्रकार का अनुमान अक्सर स्वचालित रूप से काम करता है, इसलिए आप बस identity("नमस्ते") लिख सकते हैं — TypeScript स्वयं समझ जाएगा कि T एक string है।
फ़ंक्शन में Generics: ऐरे और प्रतिबंधों के साथ काम करना
\n\nअक्सर जेनेरिक्स का उपयोग ऐरे या कलेक्शन के साथ काम करने के लिए किया जाता है। एक फ़ंक्शन पर विचार करें जो ऐरे का पहला एलिमेंट लौटाता है:
\n\nfunction getFirst<T>(arr: T[]): T | undefined {\n return arr[0];\n}\n\nconst numbers = [1, 2, 3];\nconst firstNumber = getFirst(numbers); // प्रकार number\n\nconst strings = ["a", "b", "c"];\nconst firstString = getFirst(strings); // प्रकार string\n\nध्यान दें: T[] Array<T> का संक्षिप्त रूप है। फ़ंक्शन किसी भी ऐरे के साथ काम करता है, लेकिन ठीक उसी प्रकार का एलिमेंट लौटाता है जो ऐरे में संग्रहीत है।
extends के साथ प्रतिबंध (Constraints)
\n\nकभी-कभी आवश्यकता होती है कि प्रकार T में कुछ विशिष्ट गुण हों। उदाहरण के लिए, हम किसी ऑब्जेक्ट की लंबाई प्राप्त करना चाहते हैं। सभी प्रकारों में length गुण नहीं होता, इसलिए हम एक प्रतिबंध लगा सकते हैं:
interface HasLength {\n length: number;\n}\n\nfunction getLength<T extends HasLength>(arg: T): number {\n return arg.length;\n}\n\ngetLength("स्ट्रिंग"); // OK, स्ट्रिंग में length है\ngetLength([1, 2, 3]); // OK, ऐरे में length है\ngetLength(42); // त्रुटि! संख्या में length नहीं है