हिन्दी

टाइपस्क्रिप्ट ब्रांडेड टाइप्स को जानें, जो स्ट्रक्चरल सिस्टम में नॉमिनल टाइपिंग के लिए एक शक्तिशाली तकनीक है। टाइप सुरक्षा और कोड स्पष्टता बढ़ाना सीखें।

टाइपस्क्रिप्ट ब्रांडेड टाइप्स: एक स्ट्रक्चरल सिस्टम में नॉमिनल टाइपिंग

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

स्ट्रक्चरल बनाम नॉमिनल टाइपिंग को समझना

ब्रांडेड टाइप्स में गहराई से जाने से पहले, आइए स्ट्रक्चरल और नॉमिनल टाइपिंग के बीच के अंतर को स्पष्ट करें।

स्ट्रक्चरल टाइपिंग (डक टाइपिंग)

एक स्ट्रक्चरल टाइप सिस्टम में, दो टाइप्स को संगत माना जाता है यदि उनकी संरचना समान हो (यानी, समान प्रकार के साथ समान गुण)। टाइपस्क्रिप्ट स्ट्रक्चरल टाइपिंग का उपयोग करता है। इस उदाहरण पर विचार करें:


interface Point {
  x: number;
  y: number;
}

interface Vector {
  x: number;
  y: number;
}

const point: Point = { x: 10, y: 20 };
const vector: Vector = point; // टाइपस्क्रिप्ट में मान्य

console.log(vector.x); // आउटपुट: 10

भले ही Point और Vector को अलग-अलग टाइप्स के रूप में घोषित किया गया है, टाइपस्क्रिप्ट एक Point ऑब्जेक्ट को एक Vector वैरिएबल को असाइन करने की अनुमति देता है क्योंकि उनकी संरचना समान है। यह सुविधाजनक हो सकता है, लेकिन यह तब भी त्रुटियों का कारण बन सकता है जब आपको तार्किक रूप से अलग-अलग टाइप्स के बीच अंतर करने की आवश्यकता होती है जिनकी बनावट समान हो। उदाहरण के लिए, अक्षांश/देशांतर के लिए निर्देशांक के बारे में सोचना जो संयोग से स्क्रीन पिक्सेल निर्देशांक से मेल खा सकते हैं।

नॉमिनल टाइपिंग

एक नॉमिनल टाइप सिस्टम में, टाइप्स को केवल तभी संगत माना जाता है जब उनका नाम समान हो। भले ही दो टाइप्स की संरचना समान हो, उन्हें अलग माना जाता है यदि उनके नाम अलग-अलग हों। जावा और सी# जैसी भाषाएँ नॉमिनल टाइपिंग का उपयोग करती हैं।

ब्रांडेड टाइप्स की आवश्यकता

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

ब्रांडेड टाइप्स इस मुद्दे का समाधान करते हैं, जिससे आप ऐसे विशिष्ट प्रकार बना सकते हैं जो संरचनात्मक रूप से समान हैं लेकिन टाइप सिस्टम द्वारा अलग-अलग माने जाते हैं। यह टाइप सुरक्षा को बढ़ाता है और उन त्रुटियों को रोकता है जो अन्यथा छूट सकती हैं।

टाइपस्क्रिप्ट में ब्रांडेड टाइप्स को लागू करना

ब्रांडेड टाइप्स को इंटरसेक्शन टाइप्स और एक अद्वितीय सिंबल या स्ट्रिंग लिटरल का उपयोग करके लागू किया जाता है। इसका विचार एक टाइप में "ब्रांड" जोड़ना है जो इसे समान संरचना वाले अन्य टाइप्स से अलग करता है।

सिंबल्स का उपयोग करना (अनुशंसित)

ब्रांडिंग के लिए सिंबल्स का उपयोग करना आम तौर पर बेहतर होता है क्योंकि सिंबल्स के अद्वितीय होने की गारंटी होती है।


const USD = Symbol('USD');
type USD = number & { readonly [USD]: unique symbol };

const EUR = Symbol('EUR');
type EUR = number & { readonly [EUR]: unique symbol };

function createUSD(value: number): USD {
  return value as USD;
}

function createEUR(value: number): EUR {
  return value as EUR;
}

function addUSD(a: USD, b: USD): USD {
  return (a + b) as USD;
}

const usd1 = createUSD(10);
const usd2 = createUSD(20);
const eur1 = createEUR(15);

const totalUSD = addUSD(usd1, usd2);
console.log("Total USD:", totalUSD);

// अगली लाइन को अनकम्मेंट करने पर टाइप एरर आएगा
// const invalidOperation = addUSD(usd1, eur1);

इस उदाहरण में, USD और EUR number टाइप पर आधारित ब्रांडेड टाइप्स हैं। unique symbol यह सुनिश्चित करता है कि ये टाइप्स अलग हैं। createUSD और createEUR फ़ंक्शंस का उपयोग इन टाइप्स के मान बनाने के लिए किया जाता है, और addUSD फ़ंक्शन केवल USD मान स्वीकार करता है। USD मान में EUR मान जोड़ने का प्रयास करने पर एक टाइप त्रुटि होगी।

स्ट्रिंग लिटरल्स का उपयोग करना

आप ब्रांडिंग के लिए स्ट्रिंग लिटरल्स का भी उपयोग कर सकते हैं, हालांकि यह तरीका सिंबल्स का उपयोग करने की तुलना में कम मजबूत है क्योंकि स्ट्रिंग लिटरल्स के अद्वितीय होने की गारंटी नहीं होती है।


type USD = number & { readonly __brand: 'USD' };
type EUR = number & { readonly __brand: 'EUR' };

function createUSD(value: number): USD {
  return value as USD;
}

function createEUR(value: number): EUR {
  return value as EUR;
}

function addUSD(a: USD, b: USD): USD {
  return (a + b) as USD;
}

const usd1 = createUSD(10);
const usd2 = createUSD(20);
const eur1 = createEUR(15);

const totalUSD = addUSD(usd1, usd2);
console.log("Total USD:", totalUSD);

// अगली लाइन को अनकम्मेंट करने पर टाइप एरर आएगा
// const invalidOperation = addUSD(usd1, eur1);

यह उदाहरण पिछले वाले के समान परिणाम प्राप्त करता है, लेकिन सिंबल्स के बजाय स्ट्रिंग लिटरल्स का उपयोग करता है। हालांकि यह सरल है, यह सुनिश्चित करना महत्वपूर्ण है कि ब्रांडिंग के लिए उपयोग किए जाने वाले स्ट्रिंग लिटरल्स आपके कोडबेस में अद्वितीय हों।

व्यावहारिक उदाहरण और उपयोग के मामले

ब्रांडेड टाइप्स को विभिन्न परिदृश्यों में लागू किया जा सकता है जहां आपको संरचनात्मक संगतता से परे टाइप सुरक्षा लागू करने की आवश्यकता होती है।

आईडी (IDs)

एक ऐसे सिस्टम पर विचार करें जिसमें विभिन्न प्रकार की आईडी हों, जैसे UserID, ProductID, और OrderID। ये सभी आईडी संख्या या स्ट्रिंग के रूप में प्रस्तुत की जा सकती हैं, लेकिन आप विभिन्न आईडी प्रकारों के आकस्मिक मिश्रण को रोकना चाहते हैं।


const UserIDBrand = Symbol('UserID');
type UserID = string & { readonly [UserIDBrand]: unique symbol };

const ProductIDBrand = Symbol('ProductID');
type ProductID = string & { readonly [ProductIDBrand]: unique symbol };

function getUser(id: UserID): { name: string } {
  // ... उपयोगकर्ता डेटा प्राप्त करें
  return { name: "Alice" };
}

function getProduct(id: ProductID): { name: string, price: number } {
  // ... उत्पाद डेटा प्राप्त करें
  return { name: "Example Product", price: 25 };
}

function createUserID(id: string): UserID {
  return id as UserID;
}

function createProductID(id: string): ProductID {
  return id as ProductID;
}

const userID = createUserID('user123');
const productID = createProductID('product456');

const user = getUser(userID);
const product = getProduct(productID);

console.log("User:", user);
console.log("Product:", product);

// अगली लाइन को अनकम्मेंट करने पर टाइप एरर आएगा
// const invalidCall = getUser(productID);

यह उदाहरण दिखाता है कि कैसे ब्रांडेड टाइप्स एक ProductID को एक ऐसे फ़ंक्शन में पास होने से रोक सकते हैं जो UserID की अपेक्षा करता है, जिससे टाइप सुरक्षा बढ़ती है।

डोमेन-विशिष्ट मान

ब्रांडेड टाइप्स बाधाओं के साथ डोमेन-विशिष्ट मानों का प्रतिनिधित्व करने के लिए भी उपयोगी हो सकते हैं। उदाहरण के लिए, आपके पास प्रतिशत के लिए एक टाइप हो सकता है जो हमेशा 0 और 100 के बीच होना चाहिए।


const PercentageBrand = Symbol('Percentage');
type Percentage = number & { readonly [PercentageBrand]: unique symbol };

function createPercentage(value: number): Percentage {
  if (value < 0 || value > 100) {
    throw new Error('Percentage must be between 0 and 100');
  }
  return value as Percentage;
}

function applyDiscount(price: number, discount: Percentage): number {
  return price * (1 - discount / 100);
}

try {
  const discount = createPercentage(20);
  const discountedPrice = applyDiscount(100, discount);
  console.log("Discounted Price:", discountedPrice);

  // अगली लाइन को अनकम्मेंट करने पर रनटाइम के दौरान एक त्रुटि होगी
  // const invalidPercentage = createPercentage(120);
} catch (error) {
  console.error(error);
}

यह उदाहरण दिखाता है कि रनटाइम के दौरान एक ब्रांडेड टाइप के मान पर एक बाधा कैसे लागू की जाए। जबकि टाइप सिस्टम यह गारंटी नहीं दे सकता है कि Percentage मान हमेशा 0 और 100 के बीच है, createPercentage फ़ंक्शन रनटाइम के दौरान इस बाधा को लागू कर सकता है। आप ब्रांडेड टाइप्स के रनटाइम सत्यापन को लागू करने के लिए io-ts जैसी लाइब्रेरी का भी उपयोग कर सकते हैं।

दिनांक और समय का निरूपण

विभिन्न प्रारूपों और समय क्षेत्रों के कारण तिथियों और समय के साथ काम करना मुश्किल हो सकता है। ब्रांडेड टाइप्स विभिन्न दिनांक और समय निरूपण के बीच अंतर करने में मदद कर सकते हैं।


const UTCDateBrand = Symbol('UTCDate');
type UTCDate = string & { readonly [UTCDateBrand]: unique symbol };

const LocalDateBrand = Symbol('LocalDate');
type LocalDate = string & { readonly [LocalDateBrand]: unique symbol };

function createUTCDate(dateString: string): UTCDate {
  // सत्यापित करें कि दिनांक स्ट्रिंग यूटीसी प्रारूप में है (उदाहरण के लिए, Z के साथ ISO 8601)
  if (!/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(dateString)) {
    throw new Error('Invalid UTC date format');
  }
  return dateString as UTCDate;
}

function createLocalDate(dateString: string): LocalDate {
  // सत्यापित करें कि दिनांक स्ट्रिंग स्थानीय दिनांक प्रारूप में है (उदाहरण के लिए, YYYY-MM-DD)
  if (!/\d{4}-\d{2}-\d{2}/.test(dateString)) {
    throw new Error('Invalid local date format');
  }
  return dateString as LocalDate;
}

function convertUTCDateToLocalDate(utcDate: UTCDate): LocalDate {
  // समय क्षेत्र रूपांतरण करें
  const date = new Date(utcDate);
  const localDateString = date.toLocaleDateString();
  return createLocalDate(localDateString);
}

try {
  const utcDate = createUTCDate('2024-01-20T10:00:00.000Z');
  const localDate = convertUTCDateToLocalDate(utcDate);
  console.log("UTC Date:", utcDate);
  console.log("Local Date:", localDate);
} catch (error) {
  console.error(error);
}

यह उदाहरण UTC और स्थानीय तिथियों के बीच अंतर करता है, यह सुनिश्चित करता है कि आप अपने एप्लिकेशन के विभिन्न हिस्सों में सही दिनांक और समय निरूपण के साथ काम कर रहे हैं। रनटाइम सत्यापन यह सुनिश्चित करता है कि केवल सही ढंग से स्वरूपित दिनांक स्ट्रिंग्स को ही ये प्रकार दिए जा सकते हैं।

ब्रांडेड टाइप्स का उपयोग करने के लिए सर्वोत्तम अभ्यास

टाइपस्क्रिप्ट में ब्रांडेड टाइप्स का प्रभावी ढंग से उपयोग करने के लिए, निम्नलिखित सर्वोत्तम अभ्यासों पर विचार करें:

ब्रांडेड टाइप्स के लाभ

ब्रांडेड टाइप्स के नुकसान

ब्रांडेड टाइप्स के विकल्प

जबकि ब्रांडेड टाइप्स टाइपस्क्रिप्ट में नॉमिनल टाइपिंग प्राप्त करने के लिए एक शक्तिशाली तकनीक हैं, ऐसे वैकल्पिक दृष्टिकोण हैं जिन पर आप विचार कर सकते हैं।

अपारदर्शी प्रकार (Opaque Types)

अपारदर्शी प्रकार ब्रांडेड प्रकारों के समान हैं लेकिन अंतर्निहित प्रकार को छिपाने का एक अधिक स्पष्ट तरीका प्रदान करते हैं। टाइपस्क्रिप्ट में अपारदर्शी प्रकारों के लिए अंतर्निहित समर्थन नहीं है, लेकिन आप उन्हें मॉड्यूल और निजी सिंबल्स का उपयोग करके अनुकरण कर सकते हैं।

क्लासेज (Classes)

क्लासेज का उपयोग अलग-अलग प्रकारों को परिभाषित करने के लिए एक अधिक ऑब्जेक्ट-ओरिएंटेड दृष्टिकोण प्रदान कर सकता है। जबकि टाइपस्क्रिप्ट में क्लासेज संरचनात्मक रूप से टाइप की जाती हैं, वे चिंताओं का एक स्पष्ट पृथक्करण प्रदान करते हैं और तरीकों के माध्यम से बाधाओं को लागू करने के लिए उपयोग किए जा सकते हैं।

io-ts या zod जैसी लाइब्रेरीज़

ये लाइब्रेरीज़ परिष्कृत रनटाइम टाइप सत्यापन प्रदान करती हैं और संकलन-समय और रनटाइम दोनों सुरक्षा सुनिश्चित करने के लिए ब्रांडेड प्रकारों के साथ जोड़ी जा सकती हैं।

निष्कर्ष

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

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

जैसे ही आप टाइपस्क्रिप्ट के साथ काम करते हैं, टाइप सत्यापन और प्रवर्तन के लिए उपलब्ध विभिन्न तकनीकों और लाइब्रेरीज़ का पता लगाएं। टाइप सुरक्षा के लिए एक व्यापक दृष्टिकोण प्राप्त करने के लिए io-ts या zod जैसी रनटाइम सत्यापन लाइब्रेरी के साथ ब्रांडेड प्रकारों का उपयोग करने पर विचार करें।