टाइपस्क्रिप्ट के शक्तिशाली मैप्ड और कंडीशनल टाइप्स के लिए एक व्यापक गाइड, जिसमें मजबूत और टाइप-सुरक्षित ऐप्स बनाने के लिए व्यावहारिक उदाहरण और उन्नत उपयोग शामिल हैं।
टाइपस्क्रिप्ट के मैप्ड टाइप्स और कंडीशनल टाइप्स में महारत हासिल करना
टाइपस्क्रिप्ट, जो जावास्क्रिप्ट का एक सुपरसेट है, मजबूत और रखरखाव योग्य एप्लिकेशन बनाने के लिए शक्तिशाली सुविधाएँ प्रदान करता है। इन सुविधाओं में, मैप्ड टाइप्स और कंडीशनल टाइप्स उन्नत टाइप मैनिपुलेशन के लिए आवश्यक उपकरणों के रूप में सामने आते हैं। यह गाइड इन अवधारणाओं का एक व्यापक अवलोकन प्रदान करती है, जिसमें उनके सिंटैक्स, व्यावहारिक अनुप्रयोगों और उन्नत उपयोग के मामलों की खोज की गई है। चाहे आप एक अनुभवी टाइपस्क्रिप्ट डेवलपर हों या अभी अपनी यात्रा शुरू कर रहे हों, यह लेख आपको इन सुविधाओं का प्रभावी ढंग से लाभ उठाने के ज्ञान से लैस करेगा।
मैप्ड टाइप्स क्या हैं?
मैप्ड टाइप्स आपको मौजूदा टाइप्स को रूपांतरित करके नए टाइप्स बनाने की अनुमति देते हैं। वे एक मौजूदा टाइप की प्रॉपर्टीज पर इटरेट करते हैं और प्रत्येक प्रॉपर्टी पर एक ट्रांसफॉर्मेशन लागू करते हैं। यह मौजूदा टाइप्स के वेरिएशन बनाने के लिए विशेष रूप से उपयोगी है, जैसे कि सभी प्रॉपर्टीज को वैकल्पिक या केवल-पठनीय (read-only) बनाना।
मूल सिंटैक्स
एक मैप्ड टाइप का सिंटैक्स इस प्रकार है:
type NewType<T> = {
[K in keyof T]: Transformation;
};
T
: इनपुट टाइप जिसे आप मैप करना चाहते हैं।K in keyof T
: इनपुट टाइपT
में प्रत्येक की (key) पर इटरेट करता है।keyof T
,T
में सभी प्रॉपर्टी नामों का एक यूनियन बनाता है, औरK
इटरेशन के दौरान प्रत्येक व्यक्तिगत की का प्रतिनिधित्व करता है।Transformation
: वह ट्रांसफॉर्मेशन जिसे आप प्रत्येक प्रॉपर्टी पर लागू करना चाहते हैं। यह एक मॉडिफायर (जैसेreadonly
या?
) जोड़ना, टाइप बदलना, या कुछ और हो सकता है।
व्यावहारिक उदाहरण
प्रॉपर्टीज को केवल-पठनीय (Read-Only) बनाना
मान लीजिए आपके पास एक इंटरफ़ेस है जो एक उपयोगकर्ता प्रोफ़ाइल का प्रतिनिधित्व करता है:
interface UserProfile {
name: string;
age: number;
email: string;
}
आप एक नया टाइप बना सकते हैं जहां सभी प्रॉपर्टीज केवल-पठनीय हों:
type ReadOnlyUserProfile = {
readonly [K in keyof UserProfile]: UserProfile[K];
};
अब, ReadOnlyUserProfile
में UserProfile
के समान ही प्रॉपर्टीज होंगी, लेकिन वे सभी केवल-पठनीय होंगी।
प्रॉपर्टीज को वैकल्पिक (Optional) बनाना
इसी तरह, आप सभी प्रॉपर्टीज को वैकल्पिक बना सकते हैं:
type OptionalUserProfile = {
[K in keyof UserProfile]?: UserProfile[K];
};
OptionalUserProfile
में UserProfile
की सभी प्रॉपर्टीज होंगी, लेकिन प्रत्येक प्रॉपर्टी वैकल्पिक होगी।
प्रॉपर्टी टाइप्स को संशोधित करना
आप प्रत्येक प्रॉपर्टी के टाइप को भी संशोधित कर सकते हैं। उदाहरण के लिए, आप सभी प्रॉपर्टीज को स्ट्रिंग में बदल सकते हैं:
type StringifiedUserProfile = {
[K in keyof UserProfile]: string;
};
इस मामले में, StringifiedUserProfile
में सभी प्रॉपर्टीज का टाइप string
होगा।
कंडीशनल टाइप्स क्या हैं?
कंडीशनल टाइप्स आपको ऐसे टाइप्स को परिभाषित करने की अनुमति देते हैं जो एक शर्त पर निर्भर करते हैं। वे इस आधार पर टाइप संबंधों को व्यक्त करने का एक तरीका प्रदान करते हैं कि कोई टाइप किसी विशेष बाधा को पूरा करता है या नहीं। यह जावास्क्रिप्ट में टर्नरी ऑपरेटर के समान है, लेकिन टाइप्स के लिए।
मूल सिंटैक्स
एक कंडीशनल टाइप का सिंटैक्स इस प्रकार है:
T extends U ? X : Y
T
: वह टाइप जिसकी जाँच की जा रही है।U
: वह टाइप जिसेT
द्वारा एक्सटेंड किया जा रहा है (शर्त)।X
: यदिT
,U
को एक्सटेंड करता है (शर्त सत्य है) तो वापस किया जाने वाला टाइप।Y
: यदिT
,U
को एक्सटेंड नहीं करता है (शर्त असत्य है) तो वापस किया जाने वाला टाइप।
व्यावहारिक उदाहरण
यह निर्धारित करना कि कोई टाइप स्ट्रिंग है या नहीं
आइए एक ऐसा टाइप बनाएं जो यदि इनपुट टाइप एक स्ट्रिंग है तो string
लौटाता है, और अन्यथा number
लौटाता है:
type StringOrNumber<T> = T extends string ? string : number;
type Result1 = StringOrNumber<string>; // string
type Result2 = StringOrNumber<number>; // number
type Result3 = StringOrNumber<boolean>; // number
एक यूनियन से टाइप निकालना
आप एक यूनियन टाइप से एक विशिष्ट टाइप निकालने के लिए कंडीशनल टाइप्स का उपयोग कर सकते हैं। उदाहरण के लिए, गैर-शून्य (non-nullable) टाइप्स निकालने के लिए:
type NonNullable<T> = T extends null | undefined ? never : T;
type Result4 = NonNullable<string | null | undefined>; // string
यहां, यदि T
, null
या undefined
है, तो टाइप never
हो जाता है, जिसे बाद में टाइपस्क्रिप्ट के यूनियन टाइप सरलीकरण द्वारा फ़िल्टर कर दिया जाता है।
टाइप्स का अनुमान लगाना (Inferring Types)
infer
कीवर्ड का उपयोग करके टाइप्स का अनुमान लगाने के लिए भी कंडीशनल टाइप्स का उपयोग किया जा सकता है। यह आपको एक अधिक जटिल टाइप संरचना से एक टाइप निकालने की अनुमति देता है।
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
function myFunction(x: number): string {
return x.toString();
}
type Result5 = ReturnType<typeof myFunction>; // string
इस उदाहरण में, ReturnType
एक फ़ंक्शन का रिटर्न टाइप निकालता है। यह जांचता है कि क्या T
एक ऐसा फ़ंक्शन है जो कोई भी आर्ग्यूमेंट लेता है और एक टाइप R
लौटाता है। यदि ऐसा है, तो यह R
लौटाता है; अन्यथा, यह any
लौटाता है।
मैप्ड टाइप्स और कंडीशनल टाइप्स को मिलाना
मैप्ड टाइप्स और कंडीशनल टाइप्स की असली शक्ति उन्हें मिलाने से आती है। यह आपको अत्यधिक लचीले और अभिव्यंजक टाइप ट्रांसफॉर्मेशन बनाने की अनुमति देता है।
उदाहरण: डीप रीडओनली (Deep Readonly)
एक सामान्य उपयोग का मामला एक ऐसा टाइप बनाना है जो किसी ऑब्जेक्ट की सभी प्रॉपर्टीज, जिसमें नेस्टेड प्रॉपर्टीज भी शामिल हैं, को केवल-पठनीय बनाता है। इसे एक रिकर्सिव कंडीशनल टाइप का उपयोग करके प्राप्त किया जा सकता है।
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
interface Company {
name: string;
address: {
street: string;
city: string;
};
}
type ReadonlyCompany = DeepReadonly<Company>;
यहां, DeepReadonly
रिकर्सिव रूप से सभी प्रॉपर्टीज और उनकी नेस्टेड प्रॉपर्टीज पर readonly
मॉडिफायर लागू करता है। यदि कोई प्रॉपर्टी एक ऑब्जेक्ट है, तो यह उस ऑब्जेक्ट पर रिकर्सिव रूप से DeepReadonly
को कॉल करता है। अन्यथा, यह बस प्रॉपर्टी पर readonly
मॉडिफायर लागू करता है।
उदाहरण: टाइप के अनुसार प्रॉपर्टीज को फ़िल्टर करना
मान लीजिए आप एक ऐसा टाइप बनाना चाहते हैं जिसमें केवल एक विशिष्ट टाइप की प्रॉपर्टीज शामिल हों। इसे प्राप्त करने के लिए आप मैप्ड टाइप्स और कंडीशनल टाइप्स को जोड़ सकते हैं।
type FilterByType<T, U> = {
[K in keyof T as T[K] extends U ? K : never]: T[K];
};
interface Person {
name: string;
age: number;
isEmployed: boolean;
}
type StringProperties = FilterByType<Person, string>; // { name: string; }
type NonStringProperties = Omit<Person, keyof StringProperties>;
इस उदाहरण में, FilterByType
T
की प्रॉपर्टीज पर इटरेट करता है और जाँचता है कि क्या प्रत्येक प्रॉपर्टी का टाइप U
को एक्सटेंड करता है। यदि ऐसा होता है, तो यह परिणामी टाइप में प्रॉपर्टी को शामिल करता है; अन्यथा, यह की (key) को never
पर मैप करके इसे बाहर कर देता है। कीज को रीमैप करने के लिए "as" के उपयोग पर ध्यान दें। फिर हम मूल इंटरफ़ेस से स्ट्रिंग प्रॉपर्टीज को हटाने के लिए `Omit` और `keyof StringProperties` का उपयोग करते हैं।
उन्नत उपयोग के मामले और पैटर्न
बुनियादी उदाहरणों से परे, मैप्ड टाइप्स और कंडीशनल टाइप्स का उपयोग अत्यधिक अनुकूलन योग्य और टाइप-सुरक्षित एप्लिकेशन बनाने के लिए अधिक उन्नत परिदृश्यों में किया जा सकता है।
डिस्ट्रिब्यूटिव कंडीशनल टाइप्स (Distributive Conditional Types)
कंडीशनल टाइप्स तब डिस्ट्रिब्यूटिव होते हैं जब जांचा जा रहा टाइप एक यूनियन टाइप होता है। इसका मतलब है कि शर्त यूनियन के प्रत्येक सदस्य पर व्यक्तिगत रूप से लागू होती है, और परिणामों को फिर एक नए यूनियन टाइप में जोड़ दिया जाता है।
type ToArray<T> = T extends any ? T[] : never;
type Result6 = ToArray<string | number>; // string[] | number[]
इस उदाहरण में, ToArray
को यूनियन string | number
के प्रत्येक सदस्य पर व्यक्तिगत रूप से लागू किया जाता है, जिसके परिणामस्वरूप string[] | number[]
होता है। यदि शर्त डिस्ट्रिब्यूटिव नहीं होती, तो परिणाम (string | number)[]
होता।
यूटिलिटी टाइप्स का उपयोग
टाइपस्क्रिप्ट कई अंतर्निहित यूटिलिटी टाइप्स प्रदान करता है जो मैप्ड टाइप्स और कंडीशनल टाइप्स का लाभ उठाते हैं। इन यूटिलिटी टाइप्स का उपयोग अधिक जटिल टाइप ट्रांसफॉर्मेशन के लिए बिल्डिंग ब्लॉक्स के रूप में किया जा सकता है।
Partial<T>
:T
की सभी प्रॉपर्टीज को वैकल्पिक बनाता है।Required<T>
:T
की सभी प्रॉपर्टीज को आवश्यक बनाता है।Readonly<T>
:T
की सभी प्रॉपर्टीज को केवल-पठनीय बनाता है।Pick<T, K>
:T
से प्रॉपर्टीजK
का एक सेट चुनता है।Omit<T, K>
:T
से प्रॉपर्टीजK
का एक सेट हटाता है।Record<K, T>
: टाइपT
की प्रॉपर्टीजK
के एक सेट के साथ एक टाइप बनाता है।Exclude<T, U>
:T
से उन सभी टाइप्स को बाहर करता है जोU
को असाइन किए जा सकते हैं।Extract<T, U>
:T
से उन सभी टाइप्स को निकालता है जोU
को असाइन किए जा सकते हैं।NonNullable<T>
:T
सेnull
औरundefined
को बाहर करता है।Parameters<T>
: एक फ़ंक्शन टाइपT
के पैरामीटर प्राप्त करता है।ReturnType<T>
: एक फ़ंक्शन टाइपT
का रिटर्न टाइप प्राप्त करता है।InstanceType<T>
: एक कंस्ट्रक्टर फ़ंक्शन टाइपT
का इंस्टेंस टाइप प्राप्त करता है।
ये यूटिलिटी टाइप्स शक्तिशाली उपकरण हैं जो जटिल टाइप मैनिपुलेशन को सरल बना सकते हैं। उदाहरण के लिए, आप केवल कुछ प्रॉपर्टीज को वैकल्पिक बनाने के लिए Pick
और Partial
को जोड़ सकते हैं:
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
interface Product {
id: number;
name: string;
price: number;
description: string;
}
type OptionalDescriptionProduct = Optional<Product, "description">;
इस उदाहरण में, OptionalDescriptionProduct
में Product
की सभी प्रॉपर्टीज हैं, लेकिन description
प्रॉपर्टी वैकल्पिक है।
टेम्प्लेट लिटरल टाइप्स का उपयोग
टेम्प्लेट लिटरल टाइप्स आपको स्ट्रिंग लिटरल के आधार पर टाइप बनाने की अनुमति देते हैं। उनका उपयोग मैप्ड टाइप्स और कंडीशनल टाइप्स के संयोजन में गतिशील और अभिव्यंजक टाइप ट्रांसफॉर्मेशन बनाने के लिए किया जा सकता है। उदाहरण के लिए, आप एक ऐसा टाइप बना सकते हैं जो सभी प्रॉपर्टी नामों को एक विशिष्ट स्ट्रिंग के साथ उपसर्ग करता है:
type Prefix<T, P extends string> = {
[K in keyof T as `${P}${string & K}`]: T[K];
};
interface Settings {
apiUrl: string;
timeout: number;
}
type PrefixedSettings = Prefix<Settings, "data_">;
इस उदाहरण में, PrefixedSettings
में data_apiUrl
और data_timeout
प्रॉपर्टीज होंगी।
सर्वोत्तम प्रथाएं और विचार
- इसे सरल रखें: जबकि मैप्ड टाइप्स और कंडीशनल टाइप्स शक्तिशाली हैं, वे आपके कोड को और अधिक जटिल भी बना सकते हैं। अपने टाइप ट्रांसफॉर्मेशन को यथासंभव सरल रखने का प्रयास करें।
- यूटिलिटी टाइप्स का उपयोग करें: जब भी संभव हो, टाइपस्क्रिप्ट के अंतर्निहित यूटिलिटी टाइप्स का लाभ उठाएं। वे अच्छी तरह से परीक्षित हैं और आपके कोड को सरल बना सकते हैं।
- अपने टाइप्स का दस्तावेजीकरण करें: अपने टाइप ट्रांसफॉर्मेशन का स्पष्ट रूप से दस्तावेजीकरण करें, खासकर यदि वे जटिल हैं। इससे अन्य डेवलपर्स को आपका कोड समझने में मदद मिलेगी।
- अपने टाइप्स का परीक्षण करें: यह सुनिश्चित करने के लिए कि आपके टाइप ट्रांसफॉर्मेशन अपेक्षा के अनुरूप काम कर रहे हैं, टाइपस्क्रिप्ट की टाइप चेकिंग का उपयोग करें। आप अपने टाइप्स के व्यवहार को सत्यापित करने के लिए यूनिट टेस्ट लिख सकते हैं।
- प्रदर्शन पर विचार करें: जटिल टाइप ट्रांसफॉर्मेशन आपके टाइपस्क्रिप्ट कंपाइलर के प्रदर्शन को प्रभावित कर सकते हैं। अपने टाइप्स की जटिलता के प्रति सचेत रहें और अनावश्यक गणनाओं से बचें।
निष्कर्ष
मैप्ड टाइप्स और कंडीशनल टाइप्स टाइपस्क्रिप्ट में शक्तिशाली विशेषताएं हैं जो आपको अत्यधिक लचीले और अभिव्यंजक टाइप ट्रांसफॉर्मेशन बनाने में सक्षम बनाती हैं। इन अवधारणाओं में महारत हासिल करके, आप अपने टाइपस्क्रिप्ट एप्लिकेशन की टाइप सेफ्टी, रखरखाव और समग्र गुणवत्ता में सुधार कर सकते हैं। प्रॉपर्टीज को वैकल्पिक या केवल-पठनीय बनाने जैसे सरल ट्रांसफॉर्मेशन से लेकर जटिल रिकर्सिव ट्रांसफॉर्मेशन और कंडीशनल लॉजिक तक, ये सुविधाएँ आपको मजबूत और स्केलेबल एप्लिकेशन बनाने के लिए आवश्यक उपकरण प्रदान करती हैं। इन सुविधाओं की पूरी क्षमता को अनलॉक करने और एक अधिक कुशल टाइपस्क्रिप्ट डेवलपर बनने के लिए इनकी खोज और प्रयोग करते रहें।
जैसे-जैसे आप अपनी टाइपस्क्रिप्ट यात्रा जारी रखते हैं, उपलब्ध संसाधनों का लाभ उठाना याद रखें, जिसमें आधिकारिक टाइपस्क्रिप्ट दस्तावेज़ीकरण, ऑनलाइन समुदाय और ओपन-सोर्स प्रोजेक्ट शामिल हैं। मैप्ड टाइप्स और कंडीशनल टाइप्स की शक्ति को अपनाएं, और आप सबसे चुनौतीपूर्ण टाइप-संबंधी समस्याओं से निपटने के लिए अच्छी तरह से सुसज्जित होंगे।