हिन्दी

टाइपस्क्रिप्ट के शक्तिशाली मैप्ड और कंडीशनल टाइप्स के लिए एक व्यापक गाइड, जिसमें मजबूत और टाइप-सुरक्षित ऐप्स बनाने के लिए व्यावहारिक उदाहरण और उन्नत उपयोग शामिल हैं।

टाइपस्क्रिप्ट के मैप्ड टाइप्स और कंडीशनल टाइप्स में महारत हासिल करना

टाइपस्क्रिप्ट, जो जावास्क्रिप्ट का एक सुपरसेट है, मजबूत और रखरखाव योग्य एप्लिकेशन बनाने के लिए शक्तिशाली सुविधाएँ प्रदान करता है। इन सुविधाओं में, मैप्ड टाइप्स और कंडीशनल टाइप्स उन्नत टाइप मैनिपुलेशन के लिए आवश्यक उपकरणों के रूप में सामने आते हैं। यह गाइड इन अवधारणाओं का एक व्यापक अवलोकन प्रदान करती है, जिसमें उनके सिंटैक्स, व्यावहारिक अनुप्रयोगों और उन्नत उपयोग के मामलों की खोज की गई है। चाहे आप एक अनुभवी टाइपस्क्रिप्ट डेवलपर हों या अभी अपनी यात्रा शुरू कर रहे हों, यह लेख आपको इन सुविधाओं का प्रभावी ढंग से लाभ उठाने के ज्ञान से लैस करेगा।

मैप्ड टाइप्स क्या हैं?

मैप्ड टाइप्स आपको मौजूदा टाइप्स को रूपांतरित करके नए टाइप्स बनाने की अनुमति देते हैं। वे एक मौजूदा टाइप की प्रॉपर्टीज पर इटरेट करते हैं और प्रत्येक प्रॉपर्टी पर एक ट्रांसफॉर्मेशन लागू करते हैं। यह मौजूदा टाइप्स के वेरिएशन बनाने के लिए विशेष रूप से उपयोगी है, जैसे कि सभी प्रॉपर्टीज को वैकल्पिक या केवल-पठनीय (read-only) बनाना।

मूल सिंटैक्स

एक मैप्ड टाइप का सिंटैक्स इस प्रकार है:

type NewType<T> = {
  [K in keyof T]: Transformation;
};

व्यावहारिक उदाहरण

प्रॉपर्टीज को केवल-पठनीय (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

व्यावहारिक उदाहरण

यह निर्धारित करना कि कोई टाइप स्ट्रिंग है या नहीं

आइए एक ऐसा टाइप बनाएं जो यदि इनपुट टाइप एक स्ट्रिंग है तो 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)[] होता।

यूटिलिटी टाइप्स का उपयोग

टाइपस्क्रिप्ट कई अंतर्निहित यूटिलिटी टाइप्स प्रदान करता है जो मैप्ड टाइप्स और कंडीशनल टाइप्स का लाभ उठाते हैं। इन यूटिलिटी टाइप्स का उपयोग अधिक जटिल टाइप ट्रांसफॉर्मेशन के लिए बिल्डिंग ब्लॉक्स के रूप में किया जा सकता है।

ये यूटिलिटी टाइप्स शक्तिशाली उपकरण हैं जो जटिल टाइप मैनिपुलेशन को सरल बना सकते हैं। उदाहरण के लिए, आप केवल कुछ प्रॉपर्टीज को वैकल्पिक बनाने के लिए 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 प्रॉपर्टीज होंगी।

सर्वोत्तम प्रथाएं और विचार

निष्कर्ष

मैप्ड टाइप्स और कंडीशनल टाइप्स टाइपस्क्रिप्ट में शक्तिशाली विशेषताएं हैं जो आपको अत्यधिक लचीले और अभिव्यंजक टाइप ट्रांसफॉर्मेशन बनाने में सक्षम बनाती हैं। इन अवधारणाओं में महारत हासिल करके, आप अपने टाइपस्क्रिप्ट एप्लिकेशन की टाइप सेफ्टी, रखरखाव और समग्र गुणवत्ता में सुधार कर सकते हैं। प्रॉपर्टीज को वैकल्पिक या केवल-पठनीय बनाने जैसे सरल ट्रांसफॉर्मेशन से लेकर जटिल रिकर्सिव ट्रांसफॉर्मेशन और कंडीशनल लॉजिक तक, ये सुविधाएँ आपको मजबूत और स्केलेबल एप्लिकेशन बनाने के लिए आवश्यक उपकरण प्रदान करती हैं। इन सुविधाओं की पूरी क्षमता को अनलॉक करने और एक अधिक कुशल टाइपस्क्रिप्ट डेवलपर बनने के लिए इनकी खोज और प्रयोग करते रहें।

जैसे-जैसे आप अपनी टाइपस्क्रिप्ट यात्रा जारी रखते हैं, उपलब्ध संसाधनों का लाभ उठाना याद रखें, जिसमें आधिकारिक टाइपस्क्रिप्ट दस्तावेज़ीकरण, ऑनलाइन समुदाय और ओपन-सोर्स प्रोजेक्ट शामिल हैं। मैप्ड टाइप्स और कंडीशनल टाइप्स की शक्ति को अपनाएं, और आप सबसे चुनौतीपूर्ण टाइप-संबंधी समस्याओं से निपटने के लिए अच्छी तरह से सुसज्जित होंगे।