टाइपस्क्रिप्ट में "घोषित वर्ग" और "इंटरफ़ेस" के बीच क्या अंतर है


116

टाइपस्क्रिप्ट में, .d.ts स्रोत घोषणा फ़ाइलों को बनाते समय, जो बेहतर है और क्यों?

declare class Example {
    public Method(): void; 
}

या

interface Example {
    Method(): void;
}

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



मुझे नहीं लगता कि इन दोनों में से किसी का भी वास्तव में वर्णन करने से आपको एक दूसरे पर प्रयोग करने में मदद मिलेगी क्योंकि वे दोनों एक ही चीज़ को जेएस आउटपुट के साथ पूरा कर सकते हैं।
क्रिस

1
संक्षिप्त: घोषित करने के साथ आपको यह सुनिश्चित करना होगा कि वर्ग का कार्यान्वयन रनटाइम पर मौजूद है जहां एक इंटरफ़ेस के साथ आपको नहीं करना है।
हकीम

जवाबों:


163

interfaceतब होता है जब आप किसी वस्तु के आकार का वर्णन करना चाहते हैं। इंटरफेस के लिए कोई कोड जनरेशन नहीं है - वे पूरी तरह से टाइप सिस्टम में एक कलाकृति हैं। आपको क्लास के लिए कोड जेनरेशन में कोई अंतर नहीं दिखेगा, यह इस बात पर निर्भर करता है कि उसका कोई implementsक्लॉज है या नहीं ।

declare classजब आप किसी मौजूदा वर्ग (आमतौर पर एक टाइपस्क्रिप्ट क्लास, लेकिन हमेशा नहीं) का वर्णन करना चाहते हैं , तो यह बाहरी रूप से मौजूद होने वाला है (उदाहरण के लिए, आपके पास दो .ts फ़ाइलें हैं जो दो .js फ़ाइलों के लिए संकलित हैं और दोनों scriptटैग के माध्यम से शामिल हैं। एक वेबपेज में) यदि आपको एक classउपयोग से विरासत में मिला है extends(चाहे आधार प्रकार एक declare classया एक नियमित था class), कंपाइलर प्रोटोटाइप श्रृंखला को आगे बढ़ाने के लिए सभी कोड उत्पन्न करने जा रहा है और निर्माणकर्ताओं को अग्रेषित कर रहा है और क्या नहीं।

यदि आप एक से विरासत की कोशिश करते हैं declare class उस जो एक इंटरफ़ेस होना चाहिए था, तो आपको रनटाइम त्रुटि होने वाली है क्योंकि वह उत्पन्न कोड किसी रनटाइम मैनिफ़ेस्ट वाली ऑब्जेक्ट का जिक्र होगा।

इसके विपरीत, यदि आप बस implementएक इंटरफ़ेस है जो एक होना चाहिए थाdeclare class , तो आप सभी सदस्यों को स्वयं को फिर से लागू करने जा रहे हैं और किसी भी कोड का लाभ लेने के लिए आधार-क्लास और कार्यों से फिर से उपयोग नहीं करेंगे। रनटाइम पर प्रोटोटाइप श्रृंखला की जाँच करें कि वास्तव में आधार वर्ग का एक उदाहरण नहीं होने के कारण आपकी वस्तु को अस्वीकार कर दिया जाएगा।

वास्तव में शून्य होने के लिए, यदि आपके पास C ++ पृष्ठभूमि है, तो आप मोटे interfaceतौर पर typedefऔर के declare classरूप में सोच सकते हैंextern एक निर्माता की घोषणा है कि सख्ती से इस संकलन इकाई में एक परिभाषा का अभाव है।

शुद्ध खपत पक्ष (अनिवार्य कोड लिखना, नए प्रकार नहीं जोड़ना) से, केवल एक अंतर है interfaceऔर declare classयह है कि आप newएक इंटरफ़ेस नहीं कर सकते । हालाँकि, यदि आप एक नए में इन प्रकारों में से एक extend/ करने का इरादा रखते हैं, तो आपको पूरी तरह से और के बीच सही ढंग से चुना जाना चाहिए । उनमें से केवल एक ही काम करेगा।implementclassinterfacedeclare class

दो नियम जो आपकी अच्छी सेवा करेंगे:

  • क्या कंस्ट्रक्टर फ़ंक्शन के साथ संरेखित प्रकार का नाम है (कुछ के साथ अदृश्य new) जो वास्तव में रनटाइम पर मौजूद है (उदाहरण के Dateलिए, लेकिन JQueryStaticऐसा नहीं है)? यदि नहीं , तो आप निश्चित रूप से चाहते हैंinterface
  • क्या मैं किसी अन्य टाइपस्क्रिप्ट फ़ाइल से संकलित वर्ग के साथ काम कर रहा हूँ, या कुछ समान रूप से? यदि हाँ , का उपयोग करेंdeclare class

आप वास्तव में टाइपस्क्रिप्ट में एक इंटरफ़ेस नया कर सकते हैं। केवल सीमा विरासत है।
ओलेग मिहैलिक

3
आप newऑपरेटर को इंटरफ़ेस प्रकार पर लागू नहीं कर सकते । हालांकि, इंटरफेस में हस्ताक्षर का निर्माण हो सकता है, जिसका अर्थ है कि आप newऑपरेटर को इंटरफ़ेस प्रकार के मूल्य पर आमंत्रित कर सकते हैं । यह कैसे classकाम करता है की तुलना में बहुत अलग है , जहां निर्माण हस्ताक्षर उस प्रकार की अभिव्यक्ति पर होने के बजाय स्वयं के नाम पर है।
रयान कैवानुग

यदि आप एक इंटरफ़ेस में एक कंस्ट्रक्टर को जोड़ने के मार्ग पर जाते हैं, तो यह क्लास के 'स्टेटिक्स' को छोड़कर इंटरफ़ेस का एकमात्र सदस्य होना चाहिए। कंस्ट्रक्टर फ़ंक्शन के इंटरफ़ेस को निर्मित ऑब्जेक्ट के इंटरफ़ेस के साथ संयोजित न करें। यदि आप ऐसा करते हैं, तो टाइप सिस्टम नीचता की अनुमति देता है जैसे: नया (नया x ()), जहाँ x: इंटरफ़ेस।
जेरेमी बेल

24

आप इंटरफ़ेस को लागू कर सकते हैं:

class MyClass implements Example {
    Method() {

    }
}

जबकि declare classवाक्यविन्यास वास्तव में बाहरी कोड के लिए टाइप परिभाषाओं को जोड़ने के लिए उपयोग किया जाता है जो टाइपस्क्रिप्ट में नहीं लिखा है - इसलिए कार्यान्वयन "कहीं और" है।


तो आप यह सुझाव दे रहे हैं कि टाइपस्क्रिप्ट में लिखे गए कोड का वर्णन करने के लिए घोषित वर्ग का उपयोग किया जाना चाहिए? मैं उस मामले ग्रहण करेंगे, लेकिन jquery.d.ts फ़ाइल में जाँच में, JQueryStatic द्वारा कार्यान्वित एक अंतरफलक है: घोषित वर $: JQueryStatic मैं होता है, हालांकि यह घोषणा वर्ग $ {public static ...} होने के लिए
क्रिस

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

समझ में आता है। शायद यही वजह थी।
क्रिस

ठीक है, तो मैं एक और जेएस लाइब्रेरी में घोषणाओं की ओर इशारा कर रहा हूं, इसलिए मुझे निश्चित रूप से घोषणा की आवश्यकता है। कुछ लाइब्रेरी फ़ंक्शंस (क्लासेस) पर कोड स्टैटिक्स का उपयोग कर रहा है - अभी तक मुझे एक घोषणा फ़ाइल में व्यक्त की गई स्थिर संपत्ति या विधि को देखना बाकी है। ओह, और मुझे नामस्थान या मॉड्यूल का उपयोग करना चाहिए?
जेंसन-बटन-इवेंट

13

आम आदमी की शर्तों में, संकलक को बताने के लिए / फाइलों declareमें उपयोग किया जाता है कि हमें उस वातावरण में मौजूद कीवर्ड की उम्मीद करनी चाहिए , भले ही वह वर्तमान फ़ाइल में परिभाषित न हो। यह तब हमें घोषित ऑब्जेक्ट का उपयोग करते हुए टाइप सुरक्षा करने की अनुमति देगा, क्योंकि टाइपस्क्रिप्ट कंपाइलर अब जानता है कि कुछ अन्य घटक उस चर को प्रदान कर सकते हैं।.tsd.tsdeclaring


6

declareऔर के बीच अंतरinterface TS में :

घोषित:

declare class Example {
    public Method(): void; 
}

उपरोक्त कोड declareमें TS संकलक को पता चलता है कि कहीं न कहीं वर्ग Exampleघोषित है। इसका मतलब यह नहीं है कि वर्ग जादुई रूप से शामिल है। आप एक प्रोग्रामर के रूप में उस वर्ग को उपलब्ध कराने के लिए जिम्मेदार होते हैं जब आप इसे (के साथ) घोषित कर रहे होते हैंdeclare कीवर्ड के ) ।

इंटरफेस:

interface Example {
    Method(): void;
}

एक interface वर्चुअल निर्माण है जो केवल टाइपस्क्रिप्ट के भीतर मौजूद है। टाइपस्क्रिप्ट कंपाइलर इसका उपयोग एकमात्र प्रकार की जाँच के उद्देश्य से करता है। जब कोड को जावास्क्रिप्ट के लिए संकलित किया जाता है तो इस पूरे निर्माण को छीन लिया जाएगा। टाइपस्क्रिप्ट कंपाइलर ऑब्जेक्ट्स की सही संरचना है या नहीं यह जांचने के लिए इंटरफेस का उपयोग करता है।

उदाहरण के लिए जब हमारे पास निम्न इंटरफ़ेस है:

interface test {
  foo: number,
  bar: string,
}

जिन वस्तुओं को हम परिभाषित करते हैं जिनके पास यह इंटरफ़ेस प्रकार है, उन्हें इंटरफ़ेस से बिल्कुल मेल खाना चाहिए:

// perfect match has all the properties with the right types, TS compiler will not complain.
  const obj1: test = {   
    foo: 5,
    bar: 'hey',
  }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.