2012-11-15 12 views
88

मुझे कुछ परेशानी हो रही है कि इंटरफेस में कन्स्ट्रक्टर को कैसे परिभाषित किया जाता है। मैं पूरी तरह से कुछ गलत समझ सकता है। लेकिन मैंने अच्छे समय के लिए उत्तर खोजे हैं और मुझे इससे संबंधित कुछ भी नहीं मिला है।टाइपस्क्रिप्ट निर्माण हस्ताक्षर कार्यों के साथ कैसे इंटरफेस करता है?

मैं एक टाइपप्रति कक्षा में निम्नलिखित इंटरफ़ेस कैसे लागू करते हैं:

interface MyInterface { 
    new (...) : MyInterface; 
} 

एंडर्स हेल्स्बर्ग video इस (14 के आसपास पर मिनट) में यह करने के लिए कुछ इसी तरह से युक्त एक अंतरफलक पैदा करता है। लेकिन मेरे जीवन के लिए मैं इसे कक्षा में लागू नहीं कर सकता।

मैं शायद कुछ गलत समझ रहा हूं, मुझे क्या नहीं मिल रहा है?

संपादित करें:

स्पष्टीकरण के लिए। "नया (...)" के साथ मेरा मतलब "कुछ भी" था।

interface MyInterface { 
    new() : MyInterface; 
} 

class test implements MyInterface { 
    constructor() { } 
} 

यह मेरे लिए संकलन नहीं कर रहा है मैं "मिल क्लास 'परीक्षण' वाणी इंटरफेस 'MyInterface' लेकिन इसे लागू नहीं करता है:: मेरी समस्या यह है कि मैं इस काम के भी सबसे मूल संस्करण नहीं मिल सकता है प्रकार ' MyInterface 'को एक निर्माण हस्ताक्षर की आवश्यकता है, लेकिन इसे संकलित करने का प्रयास करते समय' परीक्षण 'की कमी होती है।

संपादित करें:

तो शोध इस में थोड़ा और अधिक प्रतिक्रिया दी है।

interface MyInterface { 
    new() : MyInterface; 
} 

class test implements MyInterface { 
    constructor() => test { return this; } 
} 

मान्य टाइपस्क्रिप्ट मान्य नहीं है और इससे समस्या हल नहीं होती है। आप कन्स्ट्रक्टर के रिटर्न प्रकार को परिभाषित नहीं कर सकते हैं। यह "परीक्षण" वापस आ जाएगा। निम्न में से हस्ताक्षर: कक्षा की परीक्षा { निर्माता() {} } होने के लिए लगता है "नई() => परीक्षण" (सिर्फ इतना है कि कोड को चिपकाया गया ऑनलाइन संपादक में "वर्ग" पर मँडरा द्वारा प्राप्त)। और यह वही है जो हम चाहते हैं और मैंने सोचा कि यह क्या होगा।

क्या कोई इस उदाहरण का उदाहरण दे सकता है जहां यह वास्तव में संकलित है?

संपादित करें (फिर से ...):

तो मैं के रूप में क्यों यह एक अंतरफलक में यह परिभाषित करने के लिए संभव है, लेकिन संभव नहीं है एक टाइपप्रति class.The निम्नलिखित कार्यों में लागू करने के लिए करने के लिए एक विचार के साथ आए हैं हो सकता है :

var MyClass = (function() { 
    function MyClass() { } 
    return MyClass; 
})(); 

interface MyInterface { 
    new() : MyInterface; 
} 

var testFunction = (foo: MyInterface) : void => { } 
var bar = new MyClass(); 
testFunction(bar); 

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

+0

पहले गलत प्रतिक्रिया के लिए खेद है। मैं अभी भी देख रहा हूं, और ईमानदारी से मेरा सबसे अच्छा अनुमान यह है कि सीटीआर संरचनाएं एक प्रकार को वापस करने में सक्षम नहीं होती हैं, और इंटरफेस में एक निर्दिष्ट करने की क्षमता एक बग हो सकती है। – asawyer

+0

@asawyer हाँ यह अजीब लगता है। यह अजनबी भी है हालांकि अगर एंडर्स हेजल्सबर्ग आधिकारिक वीडियो में कुछ उपयोग करेगा जो प्रयोग योग्य नहीं है। – Nypan

+0

मैंने कोडप्लेक्स साइट पर एक प्रश्न पोस्ट किया। http://typescript.codeplex.com/discussions/403413 – asawyer

उत्तर

93

का निर्माण इंटरफेस में हस्ताक्षर कार्यान्वयन योग्य नहीं हैं:

आप अभी भी कर रहे हैं एक अंतरफलक में कंस्ट्रक्टर परिभाषित करने के लिए चाहते हैं, तो यह करने के लिए एक गंदा रास्ता है, जो मैं इस सवाल का जवाब देने के लिए प्रयोग किया जाता है कक्षाओं में; वे केवल मौजूदा जेएस एपीआई को परिभाषित करने के लिए हैं जो 'नए' सक्षम फ़ंक्शन को परिभाषित करते हैं। यहाँ इंटरफेस new हस्ताक्षर से जुड़े एक उदाहरण है कि करता है काम: ठीक उसी सवाल मैं देख कैसे चला गया के लिए

class Other implements ComesFromString { 
    constructor (public name: string, count: number) { 
    } 
} 

makeObj(Other); // Error! Other's constructor doesn't match StringConstructable 
+0

जैसा कि मुझे प्रश्न के आखिरी संपादन में संदेह था। और इसके साथ मुझे लगता है कि हम इस सवाल का जवाब दे सकते हैं। – Nypan

+28

अधिक औपचारिक रूप से, एक इंटरफेस को लागू करने वाली कक्षा कक्षा का एक * उदाहरण * पर एक अनुबंध है। चूंकि किसी वर्ग के उदाहरण में निर्माण हस्ताक्षर नहीं होगा, यह इंटरफ़ेस को संतुष्ट नहीं कर सकता है। –

+7

टाइपस्क्रिप्ट की हैंडबुक (दस्तावेज़ीकरण) में इसे हाइलाइट करना वास्तव में अच्छा होगा। – falconepl

3

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

उदाहरण के लिए

, अगर मैं एक अंतरफलक था:

interface ISimplePersistence { 
    load(id: number) : string; 
    save(id: number, data: string): void; 
} 

मैं एक कुकी, जो कोई निर्माता मानकों की जरूरत के रूप में डेटा भंडारण के लिये कार्यान्वयन हो सकता है, और एक संस्करण है कि एक डेटाबेस में डेटा संग्रहीत करता है, जो एक कन्स्ट्रक्टर पैरामीटर के रूप में एक कनेक्शन स्ट्रिंग की जरूरत है।

Interfaces with construct signatures not type checking

+0

मैं आमतौर पर इंटरफ़ेस में कन्स्ट्रक्टर समेत विचार के साथ सहमत हूं। लेकिन फिर भी, यह क्यों संभव है यदि इसे टाइपस्क्रिप्ट क्लास में कार्यान्वित करना संभव नहीं है? (आपके हैक का उपयोग किए बिना) – Nypan

+0

मुझे भाषा विनिर्देश में कुछ भी नहीं मिला है जो बताता है कि एक इंटरफेस पर कन्स्ट्रक्टर निर्दिष्ट करना संभव है। धारा 4.11 में 'नया' कीवर्ड शामिल है और केवल यह कहता है कि यह उदाहरण बनाने के लिए मान्य है, यानी 'var x = new MyClass(); '। – Fenton

+0

@SteveFenton मुझे या तो spec में कुछ भी नहीं मिल रहा है। संपादित करें - इसे पोस्ट करने के तीन सेकंड बाद नहीं - 'धारा 3.5.3.2 हस्ताक्षर बनाएं'। – asawyer

45

मेरी खोज पर:

interface ComesFromString { 
    name: string; 
} 

interface StringConstructable { 
    new(n: string): ComesFromString; 
} 

class MadeFromString implements ComesFromString { 
    constructor (public name: string) { 
     console.log('ctor invoked'); 
    } 
} 

function makeObj(n: StringConstructable) { 
    return new n('hello!'); 
} 

console.log(makeObj(MadeFromString).name); 

यह आप के साथ makeObj आह्वान कर सकते हैं क्या के लिए एक वास्तविक बाधा पैदा करता है टाइपस्क्रिप्ट-टीम ने ऐसा किया ...

वे एक इंटरफ़ेस घोषित कर रहे हैं और बाद में इंटरफ़ेस-नाम से मेल खाने वाले नाम के साथ एक चर। यह स्थिर कार्यों को टाइप करने का भी तरीका है। lib.d.ts से

उदाहरण:

interface Object { 
    toString(): string; 
    toLocaleString(): string; 
    // ... rest ... 
} 
declare var Object: { 
    new (value?: any): Object; 
    (): any; 
    (value: any): any; 
    // ... rest ... 
} 

मुझे लगता है कि कोशिश की और यह आकर्षण की तरह काम करता है।

+1

मैं एक ही पैटर्न का उपयोग कर रहा हूं, और इसे कम बदसूरत बनाने के लिए, बस एक पंक्ति में "} घोषित करें" लिखें, इसलिए यह एक ही दो-चरण निर्माण की तरह दिखता है। – setec

+1

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

0

इच्छित व्यवहार प्राप्त करने के लिए आप Decorators का उपयोग कर सकते हैं, भले ही संभवत: ऐसा नहीं है कि उनका उपयोग किया जाना चाहिए।

यह

interface MyInterface { 
    new(); 
} 

function MyInterfaceDecorator(constructor: MyInterface) { 
} 


@MyInterfaceDecorator 
class TestClass { 
    constructor() { } 
} 

एक समस्या के बिना संकलित करता है। इसके विपरीत, टेस्टक्लास

// error TS2345: Argument of type 'typeof TestClass' is not assignable to parameter of type 'MyInterface'. 
@MyInterfaceDecorator 
class TestClass { 
    constructor (arg: string) { } 
} 

संकलित नहीं होगा।

संबंधित मुद्दे