TypeScript में रनटाइम पर ऑब्जेक्ट का क्लास नाम कैसे पाएं?

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

रनटाइम पर क्लास नाम की आवश्यकता क्यों?

\n\n

कल्पना करें: आप TypeScript में एक जटिल सिस्टम लिख रहे हैं। आपके पास क्लासेज का एक पदानुक्रम है — User, Admin, Moderator। कोड की गहराई में कहीं आपको एक ऑब्जेक्ट मिलता है, लेकिन पता नहीं यह वास्तव में क्या है। कंसोल में आपको सिर्फ object दिखता है।

\n\n

या फिर आप एक लॉगर बना रहे हैं जो सिर्फ [Object] नहीं, बल्कि एक सार्थक क्लास नाम दिखाए: [User: John]। या आप एक डेकोरेटर लिख रहे हैं जो ऑब्जेक्ट के प्रकार के आधार पर तय करे कि उसे कैसे प्रोसेस करना है।

\n\n

यहीं पर Stack Overflow पर हज़ारों बार देखा गया सवाल काम आता है: "रनटाइम पर ऑब्जेक्ट का क्लास नाम प्राप्त करें"। आज हम सिर्फ जवाब नहीं देंगे, बल्कि TypeScript और JavaScript के अंदरूनी हिस्से में झांकेंगे ताकि समझ सकें कि यह वास्तव में कैसे काम करता है।

\n\n

हाँ, TypeScript JavaScript का एक सुपरसेट है। कंपाइलेशन के बाद सभी टाइप्स गायब हो जाते हैं। लेकिन क्लास का नाम कोई टाइप नहीं है, यह प्रोटोटाइप का एक गुण है। और यह रनटाइम में हमारे साथ रहता है।

\n\n

सबसे आसान तरीका: constructor.name

\n\n

अगर आपने कभी यह सवाल गूगल किया है, तो आपने शायद यह एक-लाइनर देखा होगा:

\n\n
class User {\n  constructor(public name: string) {}\n}\n\nconst user = new User("आलिया");\nconsole.log(user.constructor.name); // "User"
\n\n

काम करता है? हाँ। तेज़ है? हाँ। लेकिन इसमें कुछ बारीकियाँ हैं जो आपको परेशान कर सकती हैं अगर आप नहीं जानते कि यह कैसे काम करता है।

\n\n

यह अंदरूनी रूप से कैसे काम करता है?

\n\n

JavaScript में हर ऑब्जेक्ट में एक constructor प्रॉपर्टी होती है। यह उस फंक्शन का रेफरेंस है जिसने इस ऑब्जेक्ट को बनाया। और हर फंक्शन (क्लास भी एक फंक्शन है) में एक name प्रॉपर्टी होती है।

\n\n

जब आप user.constructor.name लिखते हैं, तो इंजन यह करता है:

\n
    \n
  • ऑब्जेक्ट user की प्रोटोटाइप चेन पर चलता है।
  • \n
  • User.prototype पर constructor प्रॉपर्टी ढूंढता है।
  • \n
  • कंस्ट्रक्टर फंक्शन User का name पढ़ता है।
  • \n
\n\n

यह एक सस्ता ऑपरेशन है, लेकिन मुफ्त नहीं है। ज़्यादातर मामलों में आपको इसका पता भी नहीं चलेगा।

\n\n

constructor.name कब काम नहीं करेगा?

\n\n

यहाँ एक क्लासिक समस्या है:

\n\n
const obj = Object.create(null);\nconsole.log(obj.constructor); // undefined\n// console.log(obj.constructor.name); // TypeError!
\n\n

Object.create(null) से बनाए गए ऑब्जेक्ट में कोई प्रोटोटाइप नहीं होता। इसमें constructor नहीं है। सावधान रहें।

\n\n

दूसरा मामला है मिनिफिकेशन। अगर आप Webpack या Terser जैसे बंडलर का उपयोग करते हैं जो क्लासेज का नाम बदल देते हैं, तो constructor.name कुछ ऐसा लौटा सकता है जैसे t या e। यह सिर्फ प्रोडक्शन में समस्या है, लेकिन इसके बारे में जानना ज़रूरी है।

\n\n

विकल्प: instanceof और कस्टम जाँच

\n\n

कभी-कभी आपको सिर्फ नाम नहीं, बल्कि यह जाँच चाहिए: "क्या यह ऑब्जेक्ट क्लास X का इंस्टेंस है?"

\n\n
class Animal {}\nclass Dog extends Animal {}\n\nconst dog = new Dog();\n\nconsole.log(dog instanceof Dog);    // true\nconsole.log(dog instanceof Animal); // true\nconsole.log(dog instanceof Object); // true
\n\n

instanceof प्रोटोटाइप चेन के माध्यम से काम करता है। यह जाँचता है कि क्या Dog.prototype ऑब्जेक्ट dog की प्रोटोटाइप चेन में मौजूद है। अगर हाँ, तो true।

\n\n

लेकिन instanceof आपको नाम के साथ एक स्ट्रिंग नहीं देता। यह सिर्फ बूलियन वैल्यू देता है। लॉग या सीरियलाइज़ेशन के लिए यह उपयुक्त नहीं है।

\n\n

संयोजन: जाँच + नाम

\n\n

आप एक यूटिलिटी लिख सकते हैं जो पहले टाइप चेक करे और फिर नाम लौटाए:

\n\n
function getClassName(obj: any): string | null {\n  if (obj === null || obj === undefined) return null;\n  if (typeof obj !== 'object' && typeof obj !== 'function') return null;\n\n  // Object.create(null) से सुरक्षा\n  if (!obj.constructor) return 'Object (कोई प्रोटोटाइप नहीं)';\n\n  const name                

ब्लॉग

पुस्तक अनुशंसाएँ