JSON Toolkit

JSON से TypeScript: interface, type guard और जनरेशन की सीमाएँ

मुख्य बात: नमूना JSON से interface उत्पन्न करना आधा काम है: वैकल्पिक फ़ील्ड, null, union, तारीखें और बड़े पूर्णांक के लिए मनुष्य का एक दौर चाहिए, और प्रकार runtime सत्यापन नहीं करते।

मध्यम~9 मिनट पढ़ें2026-10-31 को प्रकाशित2026-11-04 को अपडेट किया गया
JSON से TypeScript interface और type guard मार्गदर्शिका का कवर

सार: टाइपिंग बचाने के लिए interface उत्पन्न करें, फिर वैकल्पिकता और null दोबारा जाँचें, तारीखें और बड़े पूर्णांक स्ट्रिंग रखें, और सीमा पर runtime सत्यापन जोड़ें; जनरेट किए प्रकारों को अनुबंध मानने से आपको कोई सत्यापन नहीं मिलता।

जनरेटर केवल वही एक नमूना देखता है जो आप उसमें चिपकाते हैं। फ़ील्ड अनुपस्थित हो सकते हैं या नहीं, मान null हो सकते हैं या नहीं, और तारीखें किस प्रारूप में हैं — सब अनुमान हैं, और गलत अनुमान आपको ठीक करने हैं।

1. जनरेटर वास्तव में क्या करता है

JSON to TypeScript में नमूना चिपकाएँ और जो interface मिलता है वह आकार का सारांश होता है: यह देखी गई key और मान प्रकार गिनता है, फिर उपलब्ध सबसे संकीर्ण रूप चुनता है।

{
  "id": 1,
  "email": "ada@example.com",
  "profile": { "nickname": "Ada", "age": 36 },
  "tags": ["admin", "beta"],
  "createdAt": "2026-10-31T08:00:00Z"
}

आउटपुट लगभग ऐसा दिखता है:

interface User {
  id: number;
  email: string;
  profile: { nickname: string; age: number };
  tags: string[];
  createdAt: string;
}

यह compile होता है, पर यह एक आदर्श मान का वर्णन करता है, endpoint का असली अनुबंध नहीं। जनरेटर नहीं जानता कि email अनुपस्थित हो सकता है या नहीं, tags खाली हो सकते हैं या नहीं, या createdAt में हमेशा समय क्षेत्र होता है या नहीं। यह तो यह भी नहीं जानता कि अन्य रिकॉर्ड्स में id स्ट्रिंग हो सकता है।

इसलिए सही अपेक्षा यह है: जनरेटर टाइपिंग बचाता है, अर्थ मनुष्य देता है।

2. वैकल्पिक फ़ील्ड और null: ? और | null एक नहीं हैं

जनरेट किए आउटपुट का यही हिस्सा सबसे ज़्यादा कॉपी होता है, और सबसे ज़्यादा टूटता भी है।

TypeScript रूप अर्थ मेल खाता JSON
email: string हमेशा मौजूद, हमेशा स्ट्रिंग {"email":"a@b.c"}
email?: string Key अनुपस्थित हो सकती है; मौजूद हो तो null नहीं हो सकती {} या {"email":"a@b.c"}
email: string | null Key हमेशा मौजूद, मान null हो सकता है {"email":null}
email?: string | null Key अनुपस्थित हो सकती है और मान null भी हो सकता है तीनों मामले

जनरेटर ने एक नमूना देखा है, इसलिए वह आमतौर पर पहला रूप देता है। यदि API वास्तव में null लौटा सकता है, तो प्रकार झूठ बोल रहा है: सब कुछ compile होता है, और फिर email.toLowerCase() runtime पर फेंकता है।

इसे ठीक करने के दो तरीके हैं:

  1. कई वास्तविक नमूने इकट्ठे करें जो "key अनुपस्थित" और "मान null" दोनों को कवर करें, फिर जनरेटर से दोबारा अनुमान लगवाएँ।
  2. जनरेट करने के बाद फ़ील्ड को हाथ से ?: T | null में बदलें और कोड में दोनों शाखाएँ वास्तव में संभालें।

हर चीज़ को ?: string चिह्नित करने का शॉर्टकट न लें। Optional का अर्थ है "key मौजूद नहीं हो सकती", "मान खाली हो सकता है" नहीं। undefined और null का व्यवहार JSON.stringify में भी अलग है: पहला छोड़ दिया जाता है, दूसरा null के रूप में रखा जाता है।

3. असमान array तत्व और union प्रकार

Array सबसे आसानी से गलत पकड़ी जाने वाली संरचना है। यदि tags तीन रिकॉर्ड्स में ["admin"], [] और ["beta", 3] के रूप में आता है, तो जनरेटर string[], (string | number)[] या unknown[] दे सकता है, जो इस पर निर्भर है कि उसने कौन से नमूने देखे।

मनुष्य को तय करना होगा:

  • तत्वों के प्रकार वाकई मिश्रित हैं: (string | number)[] लिखें और उपयोग के स्थान पर narrow करें।
  • केवल एक रिकॉर्ड गंदा है: डेटा ठीक करें। उसे any[] से न छिपाएँ।
  • खाली array: जनरेटर तत्व प्रकार का अनुमान नहीं लगा सकता और never[] या any[] पर लौट आता है, इसलिए आपको उसे भरना ही होगा।
  • स्थिर लंबाई वाले tuple: [string, string] केवल तब इस्तेमाल करें जब व्यवसाय वाकई लंबाई की गारंटी देता है; वरना बाद में एक तत्व जोड़ना compile त्रुटि बन जाता है।

Object के array में भी key असमान होने पर ध्यान दें:

interface OrderItem {
  sku: string;
  quantity: number;
  discount?: number; // some records do not carry this field
}

वैकल्पिकता तत्व प्रकार पर रखें, array पर नहीं। items?: OrderItem[] का अर्थ है array स्वयं अनुपस्थित हो सकता है, जो पूरी तरह अलग कथन है।

4. तारीखें, बड़े पूर्णांक, enum: वे प्रकार जो JSON में नहीं हैं

JSON में केवल स्ट्रिंग और संख्याएँ हैं; व्यवसाय का अर्थ परंपराओं में रहता है। जनरेटर शाब्दिक रूपों से अनुमान लगाता है, इसलिए उसे हाथ से सुधारें:

JSON शाब्दिक रूप सामान्यतः जनरेट किया आउटपुट क्या होना चाहिए
"2026-10-31T08:00:00Z" string परिवहन परत में string रखें और उपयोग के स्थान पर बदलें; सीधे Date घोषित न करें
1717075200000 number मिलीसेकंड timestamp के लिए number इस्तेमाल करें और इकाई दस्तावेज़ित करें
"1234567890123456789" string इसे string ही रखें ताकि number परिशुद्धता न खोए
1 और "1" मिश्रित number | string एक रूप में सामान्यीकृत करें; union को व्यवसाय कोड में न धकेलें
"admin" string शाब्दिक union 'admin' | 'editor', या साझा enum स्थिरांक
true और "true" मिश्रित boolean | string यह प्रकार उत्पन्न करने के बजाय डेटा स्रोत ठीक करें

सबसे महत्वपूर्ण नियम: JSON में तारीखें हमेशा स्ट्रिंग होती हैं। createdAt: Date लिखना आम आत्म-धोखा है — JSON.parse कभी Date नहीं बनाता, इसलिए runtime मान अब भी स्ट्रिंग है और .getTime() फेंकता है। परिवहन प्रकार string रखें, सीमा पर स्पष्ट रूप से new Date(value) कॉल करें, और Number.isNaN जाँचें।

बड़े पूर्णांक भी वैसे ही चलते हैं। जैसे ही id 2^53 से बढ़ता है, JSON.parse पहले ही परिशुद्धता खो चुका होता है, और number उत्पन्न करना बस bug को प्रकार में पक्का कर देता है। बैकएंड स्ट्रिंग लौटाता है, फ़्रंटएंड उसे स्ट्रिंग रखता है; यही एकमात्र भरोसेमंद विकल्प है।

5. जनरेट किए प्रकार कोई runtime सत्यापन नहीं करते

TypeScript प्रकार compile समय पर मिटा दिए जाते हैं। interface कितना भी सटीक हो, वह {"id": "x"} जैसा रिस्पॉन्स नहीं रोक सकता — वह आपके अपने कोड को सीमित करता है, नेटवर्क से आ रहे बाइट को नहीं।

/**
 * Check whether a runtime value is a user object.
 * @param value The runtime value to validate
 * @returns Whether it satisfies the minimum shape of User
 */
function isUser(value: unknown): value is User {
  if (typeof value !== 'object' || value === null) {
    return false;
  }
  const candidate = value as Record<string, unknown>;
  return typeof candidate.id === 'number' && typeof candidate.email === 'string';
}

Type guard केवल उन फ़ील्ड को कवर करता है जो आप जाँच में लिखते हैं। फ़ील्ड बढ़ने के साथ हाथ से लिखे guard रखरखाव की दूसरी परिभाषा बन जाते हैं, जो interface से दूर खिसकती जाती है।

व्यावहारिक समझौता ऐसा दिखता है:

तरीका Runtime सत्यापन प्रकारों का स्रोत किसके लिए उपयुक्त
केवल interface नहीं हाथ से लिखा या जनरेट किया भरोसेमंद आंतरिक डेटा, compile-समय बाधाएँ
Interface और हाथ से लिखा guard हाँ दो परिभाषाएँ जो खिसकती हैं कम फ़ील्ड, स्पष्ट सीमा
zod / valibot हाँ schema से अनुमानित प्रकार बाहरी API, फ़ॉर्म, config
JSON Schema और validator हाँ schema से जनरेट किए प्रकार क्रॉस-भाषा अनुबंध, दस्तावेज़ीकरण

यदि डेटा बाहर से आता है, तो schema को सत्य का एकमात्र स्रोत बनाएँ और z.infer या json-schema-to-ts से प्रकार निकालें। तब "सत्यापन पार हुआ" और "प्रकार सही है" एक ही तथ्य बन जाते हैं, और खिसकने के लिए दूसरी परिभाषा नहीं रहती। पूरे दो-तरफ़ा समन्वय तरीके के लिए देखें Schema और TypeScript प्रकार समन्वय।

6. Interface या type: जनरेट किए आउटपुट पर बहस न करें

जनरेटर आमतौर पर interface देते हैं, पर ज़्यादातर स्थितियों में दोनों विनिमेय हैं। वास्तव में तीन क्षमताएँ मायने रखती हैं:

  • Declaration merging: interface को कई बार घोषित किया जा सकता है और वह स्वतः मिल जाता है; type नहीं। यह तीसरे पक्ष के प्रकारों को पैच करते समय मदद करता है, पर व्यवसाय मॉडल इससे बचें — merging "अतिरिक्त फ़ील्ड" को compiler की नज़र बचाकर आने देता है।
  • Union और mapped प्रकार: type सीधे A | B, Partial<T> और template literal प्रकार व्यक्त कर सकता है; interface नहीं।
  • Recursion: दोनों समर्थन करते हैं, पर जटिल recursive आकार type के रूप में अधिक स्वाभाविक पढ़े जाते हैं।

अधिक उपयोगी टीम नियम: object आकार के लिए interface, union, utility प्रकार और function प्रकार के लिए type इस्तेमाल करें। जनरेट किए आउटपुट को उसके डिफ़ॉल्ट पर छोड़ दें और समीक्षा का समय वैकल्पिकता तथा runtime सत्यापन पर लगाएँ।

7. टूलचेन: जनरेट करने के तीन तरीके

तरीका इनपुट ताकत सीमा
साइट का JSON to TypeScript नमूना JSON तुरंत काम करता है, स्थानीय रूप से संसाधित केवल वर्तमान नमूने पर आधारित; हाथ से narrow करना पड़ता है
quicktype JSON / JSON Schema बहु-भाषा आउटपुट, CLI एकीकरण रूढ़िवादी अनुमान, union बहुत चौड़े हो सकते हैं
json-schema-to-typescript JSON Schema अनुबंध-चालित और दोहराने योग्य पहले भरोसेमंद schema चाहिए

quicktype का एक सामान्य आह्वान:

npx quicktype -s json -o user.ts user.json --just-types

--just-types केवल प्रकार देता है और कोई runtime रूपांतरण कोड नहीं, जो उन परियोजनाओं के लिए उपयुक्त है जिनके पास पहले से पार्सिंग परत है। यदि schema हाथ से लिखा गया है या बैकएंड से आता है, तो json-schema-to-typescript बेहतर बैठता है क्योंकि वह required, enum और additionalProperties का सम्मान करता है — ऐसी बाधाएँ जिन्हें नमूना अनुमान देख ही नहीं सकता।

Schema जनरेशन के अपने जाल हैं, जैसे हर फ़ील्ड को required चिह्नित करना या null को चुपचाप optional बना देना; देखें JSON Schema जनरेटर की सामान्य गड़बड़ियाँ।

8. जनरेट किए प्रकार commit करने से पहले चेकलिस्ट

आउटपुट commit करने से पहले इन पाँच बिंदुओं से गुज़रें:

  1. फ़ील्ड नाम सामान्यीकृत करें: userId और user_id को साथ न रहने दें; रूपांतरण परत में एक बार मैप करें।
  2. वैकल्पिकता दोबारा जाँचें: वास्तविक रिस्पॉन्स से तुलना करें और खोजें कि कौन से फ़ील्ड अनुपस्थित या null हो सकते हैं।
  3. तारीखें और id स्ट्रिंग रखें: प्रकार में इकाई और प्रारूप दस्तावेज़ित करें, और उपयोग के स्थान पर स्पष्ट रूप से पार्स करें।
  4. any और unknown कम करें: जहाँ जनरेटर ने any दिया, वहाँ या तो प्रकार जोड़ें या unknown रखें और guard जोड़ें।
  5. Runtime सत्यापन जोड़ें: बाहरी डेटा कम से कम एक बार सत्यापित करें; interface से गंदा डेटा पकड़ने की अपेक्षा न रखें।

यदि परियोजना कई JSON लाइब्रेरी इस्तेमाल करती है (JSON.parse, superjson, lossless-json), तो बड़े पूर्णांक और तारीखों के लिए उनका व्यवहार अलग है, इसलिए चयन के समय इसकी पुष्टि करें। देखें JSON पार्सिंग लाइब्रेरी का चयन।

जनरेटर हर वैकल्पिक फ़ील्ड को required क्यों चिह्नित करता है?

उसने एक ही नमूना देखा, इसलिए जो भी key दिखी वह हमेशा मौजूद मान ली गई। अलग-अलग मामले कवर करने वाले कई नमूने दें, या JSON Schema से जनरेट करें — वहाँ का required array प्रामाणिक स्रोत है।

interface में Date घोषित करना runtime पर क्यों विफल होता है?

JSON.parse केवल स्ट्रिंग, संख्याएँ, boolean, null, object और array उत्पन्न करता है; वह कभी Date नहीं बनाता। Date घोषित करना compile-समय का वादा है जबकि runtime मान स्ट्रिंग ही रहता है। परिवहन परत में string रखें और सीमा पर बदलें।

क्या जनरेट किए प्रकार सत्यापन के रूप में इस्तेमाल हो सकते हैं?

नहीं। TypeScript प्रकार compile के बाद मिट जाते हैं और runtime डेटा पर कुछ नहीं थोपते। बाहरी डेटा zod, valibot, ajv या हाथ से लिखे type guard से सत्यापित करें।

बड़े पूर्णांक id को number या string टाइप करूँ?

यदि वह 2^53 से बड़ा हो सकता है, तो उसे string ही होना चाहिए। JSON.parse पार्सिंग के दौरान परिशुद्धता खो देता है, और उसे number टाइप करना बस bug को प्रकार में लिख देता है जहाँ उसे फिर सुधारा नहीं जा सकता।