टाइपस्क्रिप्ट में रिकॉर्ड प्रकार क्या है?


182

Record<K, T>टाइपस्क्रिप्ट में क्या मतलब है?

टाइपस्क्रिप्ट 2.1 ने Recordएक उदाहरण में इसका वर्णन करते हुए प्रकार पेश किया :

// For every properties K of type T, transform it to U
function mapObject<K extends string, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>

टाइपस्क्रिप्ट 2.1 देखें

और उन्नत प्रकार पृष्ठ का उल्लेख करता Recordमैप के साथ बढ़ रहा है प्रकार के तहत Readonly, Partial, और Pick, क्या इसकी परिभाषा प्रतीत होता है में:

type Record<K extends string, T> = {
    [P in K]: T;
}

रीडऑनली, आंशिक और पिक होमोमोर्फिक हैं जबकि रिकॉर्ड नहीं है। एक सुराग जो रिकॉर्ड होमोमोर्फिक नहीं है, वह यह है कि गुणों से कॉपी करने के लिए इनपुट प्रकार नहीं लिया जाता है:

type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>

और बस। उपरोक्त उद्धरणों के अलावा, typecriptlang.orgRecord पर कोई अन्य उल्लेख नहीं है ।

प्रशन

  1. क्या कोई सरल परिभाषा दे सकता है कि क्या Recordहै?

  2. क्या Record<K,T>केवल कहने का एक तरीका है "इस वस्तु पर सभी गुण टाइप होंगे T"? शायद सभी गुण नहीं , क्योंकि Kकुछ उद्देश्य है ...

  3. क्या Kजेनेरिक ऑब्जेक्ट पर अतिरिक्त कुंजियों को मना Kकरता है, या यह उन्हें अनुमति नहीं देता है और केवल संकेत देता है कि उनके गुणों को रूपांतरित नहीं किया गया है T?

  4. दिए गए उदाहरण के साथ:

     type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>

क्या यह वास्तव में ऐसा ही है ?:

    type ThreeStringProps = {prop1: string, prop2: string, prop3: string}

6
4. का उत्तर बहुत अधिक "हाँ" है, इसलिए संभवतः आपके अन्य प्रश्नों का उत्तर देना चाहिए।
jcalz

जवाबों:


210
  1. क्या कोई सरल परिभाषा दे सकता है कि क्या Recordहै?

A Record<K, T>एक ऑब्जेक्ट प्रकार है जिसकी संपत्ति कुंजियाँ हैं Kऔर जिनके गुण मान हैं T। अर्थात, keyof Record<K, T>के बराबर है Kऔर Record<K, T>[K](मूल रूप से) के बराबर है T

  1. क्या Record<K,T>केवल कहने का एक तरीका है "इस वस्तु पर सभी गुण टाइप होंगे T"? शायद सभी वस्तुओं को नहीं, क्योंकि Kकुछ उद्देश्य है ...

जैसा कि आप ध्यान दें, Kएक उद्देश्य है ... संपत्ति कुंजी को विशेष मूल्यों तक सीमित करना। यदि आप सभी संभावित स्ट्रिंग-वैल्यू कीज़ को स्वीकार करना चाहते हैं, तो आप कुछ ऐसा कर सकते हैं Record<string, T>, लेकिन ऐसा करने का मुहावरेदार तरीका है जैसे इंडेक्स सिग्नेचर का उपयोग करना { [k: string]: T }

  1. क्या Kजेनेरिक ऑब्जेक्ट पर अतिरिक्त कुंजियों को मना Kकरता है, या यह उन्हें अनुमति नहीं देता है और केवल संकेत देता है कि उनके गुणों को रूपांतरित नहीं किया गया है T?

यह अतिरिक्त कुंजियों को "निषिद्ध" बिल्कुल नहीं करता है: आखिरकार, एक मूल्य को आम तौर पर अपने प्रकार के गुणों का स्पष्ट रूप से उल्लेख नहीं करने की अनुमति है ... लेकिन यह नहीं पहचाना जाएगा कि ऐसे गुण मौजूद हैं:

declare const x: Record<"a", string>;
x.b; // error, Property 'b' does not exist on type 'Record<"a", string>'

और यह उन्हें अतिरिक्त गुणों के रूप में मानता है जिन्हें कभी-कभी अस्वीकार कर दिया जाता है:

declare function acceptR(x: Record<"a", string>): void;
acceptR({a: "hey", b: "you"}); // error, Object literal may only specify known properties

और कभी-कभी स्वीकार किया जाता है:

const y = {a: "hey", b: "you"};
acceptR(y); // okay
  1. दिए गए उदाहरण के साथ:

    type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>

    क्या यह वास्तव में ऐसा ही है ?:

    type ThreeStringProps = {prop1: string, prop2: string, prop3: string}

हाँ!

उम्मीद है की वो मदद करदे। सौभाग्य!


1
बहुत ज्यादा सीखा और एक सवाल "क्यों एक सूचकांक हस्ताक्षर का उपयोग करने का एक मुहावरेदार तरीका है" रिकॉर्ड एक नहीं? मुझे इस "मुहावरेदार तरीके" के बारे में कोई संबंधित जानकारी नहीं मिली है।
किंवदंती80s

2
आप चाहें तो Record<string, V>इसका उपयोग कर सकते {[x: string]: V}हैं; मैंने शायद खुद भी ऐसा किया है। सूचकांक हस्ताक्षर संस्करण अधिक प्रत्यक्ष है: वे एक ही प्रकार हैं, लेकिन पूर्व एक मैप किए गए प्रकार का उपनाम है जो एक सूचकांक हस्ताक्षर का मूल्यांकन करता है, जबकि बाद वाला सीधे सूचकांक हस्ताक्षर है। बाकी सभी समान हैं, मैं बाद की सिफारिश करूंगा। इसी तरह जब तक कुछ अन्य सम्मोहक प्रासंगिक कारण नहीं थे Record<"a", string>, {a: string}तब तक मैं इसका उपयोग नहीं करूंगा ।
13

1
" बाकी सभी समान हैं, मैं बाद की सिफारिश करूंगा। " ऐसा क्यों है? मेरे पूर्व-टाइपस्क्रिप्ट स्वयं सहमत हैं, लेकिन मुझे पता है कि पूर्व अधिक होगा, उम, सी # तरफ से आने वाले लोगों के लिए स्वयं-टिप्पणी, उदाहरण के लिए, और जावास्क्रिप्ट-टू-टाइपस्क्रिप्ट के लिए कोई भी बदतर नहीं है। क्या आप सिर्फ उन निर्माणों के लिए वाष्पीकरण कदम को रोकने में रुचि रखते हैं?
रफिन

1
बस मेरी राय: Record<string, V>यदि आप पहले से ही जानते हैं कि टाइपस्क्रिप्ट में इंडेक्स हस्ताक्षर कैसे काम करते हैं, तो केवल यह समझ में आता है। उदाहरण के लिए, दिया गया x: Record<string, string>, x.fooजाहिरा तौर पर एक stringसंकलन समय पर होगा, लेकिन वास्तविकता में होने की संभावना है string | undefined। यह एक अंतराल है कि कैसे --strictNullChecksकाम करता है ( # 13778 देखें )। मैं इसके बजाय नए लोगों से {[x: string]: V}सीधे अनुक्रमणिका व्यवहार के Record<string, V>माध्यम से श्रृंखला का पालन करने की उम्मीद करने के बजाय उनसे निपटना चाहूंगा {[P in string]: V}
jcalz

मैं यह इंगित करना चाहता था कि तार्किक रूप से एक प्रकार को सभी प्रकारों के एक सेट के रूप में परिभाषित किया जा सकता है। इस व्याख्या को देखते हुए मुझे लगता है कि रिकॉर्ड <string, V> एक अमूर्त के रूप में उचित है कि सभी संभावित मूल्यों को बिछाने के बजाय कोड को सरल बनाया जाए। यह उपयोगिता प्रकार के प्रलेखन में उदाहरण के समान है: रिकॉर्ड <टी, वी> जहां टाइप टी = 'ए' | 'बी' | 'सी'। कभी नहीं कर रहा रिकॉर्ड <'a', string> एक अच्छा काउंटर उदाहरण नहीं है, क्योंकि यह एक ही पैटर्न का पालन नहीं करता है। यह अमूर्त के माध्यम से कोड को पुन: उपयोग या सरल करने के लिए भी नहीं जोड़ता है जैसा कि अन्य उदाहरण करते हैं।
स्कॉट लियोनार्ड

68

एक रिकॉर्ड आपको संघ से एक नया प्रकार बनाने की सुविधा देता है। संघ में मूल्यों का उपयोग नए प्रकार की विशेषताओं के रूप में किया जाता है।

उदाहरण के लिए, मान लीजिए कि मेरे पास एक संघ है:

type CatNames = "miffy" | "boris" | "mordred";

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

type CatList = Record<CatNames, {age: number}>

यदि मैं इस कैटालिस्ट को संतुष्ट करना चाहता हूं, तो मुझे इस तरह से एक ऑब्जेक्ट बनाना होगा:

const cats:CatList = {
  miffy: { age:99 },
  boris: { age:16 },
  mordred: { age:600 }
}

आपको बहुत मजबूत प्रकार की सुरक्षा मिलती है:

  • यदि मैं एक बिल्ली को भूल जाता हूं, तो मुझे एक त्रुटि मिलती है।
  • यदि मैं एक बिल्ली जोड़ता हूं जिसकी अनुमति नहीं है, तो मुझे एक त्रुटि मिलती है।
  • यदि मैं बाद में कैटनेम बदल देता हूं, तो मुझे एक त्रुटि मिलती है। यह विशेष रूप से उपयोगी है क्योंकि CatNames को संभवतः किसी अन्य फ़ाइल से आयात किया जाता है, और कई स्थानों पर उपयोग किया जाता है।

वास्तविक दुनिया प्रतिक्रिया उदाहरण।

मैंने हाल ही में एक स्थिति घटक बनाने के लिए इसका उपयोग किया था। घटक को एक स्थिति प्रोप प्राप्त होगा, और फिर एक आइकन प्रस्तुत करना होगा। मैंने चित्रण के उद्देश्य से यहां कोड को काफी सरल बना दिया है

मेरा संघ इस तरह था:

type Statuses = "failed" | "complete";

मैंने इसका उपयोग इस तरह एक वस्तु बनाने के लिए किया है:

const icons: Record<
  Statuses,
  { iconType: IconTypes; iconColor: IconColors }
> = {
  failed: {
    iconType: "warning",
    iconColor: "red"
  },
  complete: {
    iconType: "check",
    iconColor: "green"
  };

मैं तब वस्तु से एक तत्व को प्रॉप्स में नष्ट करके प्रस्तुत कर सकता था, जैसे:

const Status = ({status}) => <Icon {...icons[status]} />

यदि स्टेटस यूनियन बाद में विस्तारित या परिवर्तित हो जाता है, तो मुझे पता है कि मेरा स्टेटस कंपोनेंट संकलन में विफल हो जाएगा और मुझे एक त्रुटि मिलेगी जिसे मैं तुरंत ठीक कर सकता हूं। यह मुझे एप्लिकेशन में अतिरिक्त त्रुटि राज्यों को जोड़ने की अनुमति देता है।

ध्यान दें कि वास्तविक ऐप में दर्जनों त्रुटि राज्य थे जिन्हें कई स्थानों पर संदर्भित किया गया था, इसलिए इस प्रकार की सुरक्षा बेहद उपयोगी थी।


मुझे लगता है कि ज्यादातर समय type Statusesआपके द्वारा परिभाषित टाइपिंग में नहीं रहता है? अन्यथा मैं एक इंटरफ़ेस के साथ कुछ देख सकता हूं जैसे कि एनम एक बेहतर फिट है?
विक्टोरियो बेर्रा

हाय @victorio, मुझे यकीन नहीं है कि कैसे एक एनुम समस्या को हल करेगा, यदि आपको एक कुंजी याद आती है तो आपको एनम में कोई त्रुटि नहीं मिलती है। यह कुंजी और मूल्यों के बीच एक मानचित्रण है।
३l पर सुपरलीनरी

1
मैं देख सकता हूं कि तुम्हरा अब क्या मतलब है। C # से आने पर हमारे पास ऐसा करने के लिए चतुर तरीके नहीं हैं। निकटतम चीज़ का एक शब्दकोष होगा Dictionary<enum, additional_metadata>। रिकॉर्ड प्रकार उस एनम + मेटाडेटा पैटर्न का प्रतिनिधित्व करने का एक शानदार तरीका है।
विक्टोरियो बेर्रा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.