Kodokon kodokon.com

उन्नत generics: constraints और defaults

आप extends के साथ अपने टाइप parameters को सीमित करते हैं और सुविधाजनक generic APIs बनाने के लिए defaults प्रदान करते हैं।

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

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

एक असीमित generic अपारदर्शी होता है: function body के अंदर, T आपको कुछ भी करने नहीं देता। extends क्लॉज़ टाइप parameter पर एक न्यूनतम अनुबंध स्थापित करता है, जो caller के सटीक टाइप को बनाए रखते हुए गारंटीशुदा properties तक पहुँच को अनलॉक करता है। यही किसी interface से typed parameter की तुलना में मूलभूत अंतर है: constraint जानकारी को बनाए रखता है, interface उसे मिटा देता है।

TYPESCRIPT
function longest<T extends { length: number }>(
  a: T,
  b: T
): T {
  return a.length >= b.length ? a : b;
}

const word = longest("hello", "worldwide");
const list = longest([1, 2], [3, 4, 5]);
word string के रूप में typed रहता है, list number[] के रूप में।

K extends keyof T जोड़ी रोज़मर्रा का सबसे लाभदायक pattern है: यह दो टाइप parameters को आपस में जोड़ती है और स्थिर रूप से गारंटी देती है कि कोई key वास्तव में object से संबंधित है। T[K] return टाइप (एक indexed access type) अनुरोधित property को सटीक रूप से ट्रैक करता है। utility libraries के pick या pluck जैसे functions ठीक इसी तरह typed होते हैं।

TYPESCRIPT
function getProp<T extends object, K extends keyof T>(
  obj: T,
  key: K
): T[K] {
  return obj[key];
}

const config = { port: 8080, host: "localhost" };
const port = getProp(config, "port");
const host = getProp(config, "host");
port को number के रूप में infer किया जाता है, host को string के रूप में; कोई भी अन्य key अस्वीकार कर दी जाती है।

Defaults (T = string) call site पर एक generic को वैकल्पिक बना देते हैं: उपयोगकर्ता टाइप argument तभी प्रदान करते हैं जब वे सामान्य मामले से हटना चाहते हैं। किसी constraint के साथ मिलकर (T extends X = Y), वे सीमा और अंतर्निहित व्यवहार दोनों को परिभाषित करते हैं। default को constraint को संतुष्ट करना होता है, अन्यथा घोषणा स्वयं compile नहीं होती। यह HTTP clients, stores, और typed event emitters के लिए मानक pattern है।

TYPESCRIPT
interface ApiResponse<T = unknown> {
  status: number;
  data: T;
}

async function fetchJson<T = unknown>(
  url: string
): Promise<ApiResponse<T>> {
  const res = await fetch(url);
  return { status: res.status, data: await res.json() };
}

interface Post { id: number; title: string }
const typed = await fetchJson<Post>("/api/posts/1");
const loose = await fetchJson("/api/health");
टाइप argument के बिना, data any के बजाय unknown पर वापस आ जाता है।

ज्ञान जांच

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

  1. किसी generic signature में constraint K extends keyof T क्या गारंटी देता है?
    • कि K कोई भी string है
    • कि K, T की एक मौजूदा key है, जो compile time पर जाँची जाती है
    • कि T में कम से कम एक वैकल्पिक key है
    • कि K और T एक ही टाइप हैं
  2. generics के बिना longest(a: { length: number }, b: ...) की तुलना में longest<T extends { length: number }> का क्या लाभ है?
    • यह तेज़ चलता है
    • यह return मान में caller के सटीक टाइप को बनाए रखता है
    • यह अधिक input टाइप स्वीकार करता है
  3. default मान के रूप में <T = any> की तुलना में <T = unknown> को क्यों प्राथमिकता दें?
    • unknown, any की तुलना में तेज़ी से compile होता है
    • strict mode में any निषिद्ध है
    • unknown caller को उपयोग से पहले टाइप narrow करने के लिए बाध्य करता है, any सभी जाँच को बंद कर देता है
    • unknown, any की तुलना में कम मान स्वीकार करता है