Kodokon kodokon.com

प्रोडक्शन पैटर्न: ब्रांडेड टाइप्स, satisfies, और .d.ts

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

11 मिनट · 3 प्रश्न

इस पाठ को Kodokon में खोलें

TypeScript की टाइपिंग संरचनात्मक (structural) है: एक ही आकार वाले दो टाइप्स आपस में विनिमेय होते हैं, इसलिए एक user-id string किसी भी अन्य string से अप्रभेद्य है। ब्रांडिंग आधार टाइप को एक फ़ैंटम प्रॉपर्टी के साथ इंटरसेक्ट करके नामिक टाइपिंग का अनुकरण करती है जिसकी की एक unique symbol होती है: कोई भी वास्तविक मान इसे कभी नहीं रखता, लेकिन अब कंपाइलर प्रत्येक ब्रांड को अलग पहचान लेता है।

TYPESCRIPT
declare const brand: unique symbol;

type Brand<T, Name extends string> =
  T & { readonly [brand]: Name };

type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;

function asUserId(raw: string): UserId {
  return raw as UserId;
}

declare function loadUser(id: UserId): void;

loadUser(asUserId("u_42")); // OK
// loadUser("u_42"); // error: bare string rejected
सिमुलेटेड नामिकता, शून्य रनटाइम लागत पर।

satisfies ऑपरेटर (TypeScript 4.9) एक सटीक कमी को भरता है। एक : T एनोटेशन वेरिएबल के टाइप को T तक चौड़ा (widen) कर देता है और अनुमानित लिटरल्स खो देता है; एक as T जांचों के एक हिस्से को अक्षम कर देता है। satisfies T सत्यापित करता है कि एक्सप्रेशन T के अनुरूप है बिना अनुमानित टाइप को छुए, जो यथासंभव सटीक बना रहता है। यह कॉन्फ़िगरेशन ऑब्जेक्ट्स के लिए आदर्श उपकरण है: पूर्ण वैलिडेशन, सटीकता बरकरार।

TYPESCRIPT
type RouteDef = { path: string; auth?: boolean };

const routes = {
  home: { path: "/" },
  admin: { path: "/admin", auth: true },
} satisfies Record<string, RouteDef>;

routes.admin.auth;
// literal type true: the inferred precision is
// preserved, and an unknown key would be rejected
satisfies: बिना वाइडनिंग के सख्त जांच।

एक .d.ts फ़ाइल में केवल ऐम्बिएंट घोषणाएं (ambient declarations) होती हैं: यह उन मानों का वर्णन करती है जो रनटाइम पर मौजूद रहेंगे, बिना JavaScript की एक भी पंक्ति उत्सर्जित किए। किसी मॉड्यूल से ग्लोबल स्कोप का विस्तार करने के लिए, declare global ब्लॉक अनिवार्य है - और विनिर्देश इसे केवल उसी फ़ाइल में अनुमति देता है जो वास्तव में एक मॉड्यूल हो, इसलिए फ़ाइल के शीर्ष पर export {} मुहावरा।

TYPESCRIPT
export {};

declare global {
  interface Window {
    analytics: { track(event: string): void };
  }
}
env.d.ts: export {} फ़ाइल को एक मॉड्यूल में बदल देता है।

बिना प्रकाशित टाइप्स वाली किसी JavaScript डिपेंडेंसी के लिए, declare module एक ऐम्बिएंट मॉड्यूल बनाता है: कंपाइलर पैकेज के प्रत्येक इंपोर्ट के लिए आपकी घोषणा का उपयोग करेगा। skipLibCheck के दायरे से सावधान रहें: सक्षम होने पर, यह सभी .d.ts फ़ाइलों से त्रुटियों को अनदेखा कर देता है, जिसमें आपकी भी शामिल हैं; इसलिए अपनी घोषणाओं को साधारण .ts फ़ाइलों में रखे गए टाइप टेस्ट के माध्यम से सत्यापित करें।

TYPESCRIPT
declare module "legacy-lib" {
  export interface InitOptions {
    debug?: boolean;
  }
  export function init(options?: InitOptions): void;
}
legacy-lib.d.ts: बिना प्रकाशित टाइप्स वाले पैकेज को टाइप करना।

ज्ञान जांच

सुनिश्चित करें कि आपको इस पाठ के मुख्य बिंदु याद हैं।

  1. satisfies T और एक : T एनोटेशन के बीच क्या अंतर है?
    • satisfies एक्सप्रेशन के टाइप को T तक चौड़ा कर देता है
    • satisfies अधिक सटीक अनुमानित टाइप को बनाए रखते हुए T के अनुरूपता की जांच करता है
    • satisfies जांचों को अक्षम कर देता है, जैसे as
    • कोई नहीं: दोनों रूप समतुल्य हैं
  2. रनटाइम पर, Brand<string, ...> के साथ बनाया गया एक ब्रांडेड मान क्या रखता है?
    • एक symbol प्रॉपर्टी के साथ एक string
    • एक सादा string: ब्रांड केवल कंपाइल टाइम पर मौजूद रहता है
    • मूल स्ट्रिंग को लपेटने वाला एक ऑब्जेक्ट
  3. declare global का उपयोग करने वाली .d.ts फ़ाइल के शीर्ष पर export {} क्यों जोड़ें?
    • ग्लोबल टाइप्स को अन्य फ़ाइलों में एक्सपोर्ट करने के लिए
    • फ़ाइल को एक मॉड्यूल में बदलने के लिए, जो declare global के लिए आवश्यक एक शर्त है
    • स्वचालित रूप से स्ट्रिक्ट मोड सक्षम करने के लिए
    • यह विशुद्ध रूप से सजावटी है