टाइपस्क्रिप्ट कॉलबैक प्रकार को परिभाषित करना


172

मुझे टाइपस्क्रिप्ट में निम्न वर्ग मिला है:

class CallbackTest
{
    public myCallback;

    public doWork(): void
    {
        //doing some work...
        this.myCallback(); //calling callback
    }
}

मैं इस तरह वर्ग का उपयोग कर रहा हूं:

var test = new CallbackTest();
test.myCallback = () => alert("done");
test.doWork();

कोड काम करता है, इसलिए यह उम्मीद के मुताबिक एक संदेश बॉक्स प्रदर्शित करता है।

मेरा प्रश्न यह है: क्या कोई प्रकार है जो मैं अपने वर्ग क्षेत्र के लिए प्रदान कर सकता हूं myCallback? अभी, सार्वजनिक क्षेत्र myCallbackप्रकार का है anyजैसा कि ऊपर दिखाया गया है। मैं कॉलबैक की विधि हस्ताक्षर को कैसे परिभाषित कर सकता हूं? या मैं सिर्फ कॉलबैक-टाइप के कुछ प्रकार सेट कर सकता हूं? या मैं इनमें से क्या कर सकता हूँ? क्या मुझे any(अंतर्निहित / स्पष्ट) उपयोग करना है?

मैंने कुछ इस तरह की कोशिश की, लेकिन यह काम नहीं किया (संकलन-समय त्रुटि):

public myCallback: ();
// or:
public myCallback: function;

मुझे इसका कोई स्पष्टीकरण ऑनलाइन नहीं मिला, इसलिए मुझे उम्मीद है कि आप मेरी मदद कर सकते हैं।

जवाबों:


211

मुझे टाइपस्क्रिप्ट भाषा विनिर्देश में बस कुछ मिला, यह काफी आसान है। मैं काफ़ी करीब था।

वाक्य रचना निम्नलिखित है:

public myCallback: (name: type) => returntype;

मेरे उदाहरण में, यह होगा

class CallbackTest
{
    public myCallback: () => void;

    public doWork(): void
    {
        //doing some work...
        this.myCallback(); //calling callback
    }
}

8
मुझे कॉलबैक हस्ताक्षर को परिभाषित करने के लिए पैरामीटर नाम की आवश्यकता क्यों नहीं है ...
2gr

4
मुझे लगता है कि यह C # टीम की कुछ सांस्कृतिक विरासत हो सकती है , मुझे लगता है कि मुझे यह सब पसंद है ...
2grit 11'17 को

क्या आप दस्तावेज़ के उस पृष्ठ का लिंक प्रदान कर सकते हैं?
jcairney

यह एक अच्छा लिंक हो सकता है fettblog.eu/typescript-substitutability
nilakantha singh deo

147

एक कदम आगे जाने के लिए, आप फ़ंक्शन हस्ताक्षर के लिए एक प्रकार का सूचक घोषित कर सकते हैं जैसे:

interface myCallbackType { (myArgument: string): void }

और इसे इस तरह उपयोग करें:

public myCallback : myCallbackType;

9
यह (IMO) स्वीकृत उत्तर की तुलना में बहुत बेहतर समाधान है, क्योंकि यह आपको एक प्रकार को परिभाषित करने देता है और फिर कहता है, उस प्रकार का एक पैरामीटर (कॉलबैक) पास करें जिसे आप किसी भी तरीके से उपयोग कर सकते हैं, जिसमें कॉल करना शामिल है। स्वीकृत उत्तर एक सदस्य चर का उपयोग करता है और आपको अपने कार्य के लिए सदस्य चर सेट करना होगा, फिर एक विधि को कॉल करें - बदसूरत और त्रुटियों के लिए प्रवण, क्योंकि पहले चर को सेट करना विधि को कॉल करने के अनुबंध का हिस्सा है।
डेविड

यह आपको आसानी से कॉलबैक को अशक्त के रूप में सेट करने देता है, जैसेlet callback: myCallbackType|null = null;
Doches

1
ध्यान दें कि TSLint शिकायत करेगा "TSLint: इंटरफ़ेस में केवल एक कॉल हस्ताक्षर है - type MyHandler = (myArgument: string) => voidइसके बजाय उपयोग करें । ( कॉल करने योग्य-प्रकार)" ; टीएसवी का जवाब
अर्जन

इस उत्तर के पहले मसौदे ने वास्तव में उस समस्या को हल कर दिया जिसने मुझे इस सवाल का नेतृत्व किया। मैं एक इंटरफ़ेस के भीतर एक अनुमेय पर्याप्त फ़ंक्शन हस्ताक्षर को परिभाषित करने की कोशिश कर रहा था जो कंपाइलर त्रुटि पैदा किए बिना किसी भी संख्या में मापदंडों को स्वीकार कर सकता था। मेरे मामले में जवाब का उपयोग करना था ...args: any[]। उदाहरण: निर्यात इंटरफ़ेस MyInterface {/ ** एक कॉलबैक फ़ंक्शन। / कॉलबैक: (... आर्ग: कोई []) => कोई भी, / * कॉलबैक फ़ंक्शन के लिए पैरामीटर। * [कॉलबैकपराम: कोई []}
केन ल्योन

61

आप एक नए प्रकार की घोषणा कर सकते हैं:

declare type MyHandler = (myArgument: string) => void;

var handler: MyHandler;

अपडेट करें।

declareकीवर्ड आवश्यक नहीं है। इसका उपयोग .d.ts फ़ाइलों या इसी तरह के मामलों में किया जाना चाहिए।


मुझे इसके लिए दस्तावेज़ कहां से मिलेंगे?
ई। सुंदरिन

@ E.Sundin - धारा के "प्रकार उपनाम" typescriptlang.org/docs/handbook/advanced-types.html
TSV

1
जबकि यह जानने के लिए सही और अच्छा है, एक ही पृष्ठ (आजकल) यह भी कहता है "क्योंकि सॉफ्टवेयर की एक आदर्श संपत्ति का विस्तार हो रहा है, आपको हमेशा संभव हो तो एक प्रकार के उपनाम पर इंटरफ़ेस का उपयोग करना चाहिए।"
अर्जन

@ अर्जन - वस्तुओं के लिए मैं इससे पूरी तरह सहमत हूँ। क्या आप निर्दिष्ट कर सकते हैं - आप किसी फ़ंक्शन का विस्तार कैसे करना चाहते हैं?
TSV

ध्यान दें कि प्रकार की घोषणा वैकल्पिक है: var handler: (myArgument: string) => voidवाक्यात्मक रूप से मान्य है (यदि थोड़ा गड़बड़ है)।
हच

35

यहाँ एक उदाहरण है - बिना किसी पैरामीटर के स्वीकार करना और कुछ भी नहीं लौटाना।

class CallbackTest
{
    public myCallback: {(): void;};

    public doWork(): void
    {
        //doing some work...
        this.myCallback(); //calling callback
    }
}

var test = new CallbackTest();
test.myCallback = () => alert("done");
test.doWork();

यदि आप एक पैरामीटर स्वीकार करना चाहते हैं, तो आप उसे भी जोड़ सकते हैं:

public myCallback: {(msg: string): void;};

और यदि आप एक मूल्य वापस करना चाहते हैं, तो आप उसे भी जोड़ सकते हैं:

public myCallback: {(msg: string): number;};

कार्यात्मक रूप से वे समान हैं - वे एक ही चीज को परिभाषित करते हैं और आपको फ़ंक्शन हस्ताक्षर पर टाइपिंग की जांच देते हैं। आप जो भी चाहें उसका उपयोग कर सकते हैं। युक्ति कहती है कि वे हैं exactly equivalent
फेंटन

6
@nikeee: सवाल यह है कि आपके उत्तर के साथ क्या अलग है? स्टीव ने अपना जवाब आपके सामने पोस्ट किया।
jgauffin

@jgauffin वास्तव में, परिणाम समान है। IMO समाधान मैंने पोस्ट किया जब कॉलबैक के बारे में बात करना अधिक स्वाभाविक है, क्योंकि स्टीव का संस्करण संपूर्ण इंटरफ़ेस परिभाषाओं की अनुमति देता है। यह आपकी पसंद पर निर्भर करता है।
नाइके

@ फ़ेंटन क्या आप कृपया उस दस्तावेज़ का लिंक प्रदान कर सकते हैं?
jcairney

17

यदि आप एक सामान्य कार्य चाहते हैं, तो आप निम्नलिखित का उपयोग कर सकते हैं। हालांकि यह कहीं भी प्रलेखित नहीं लगता है।

class CallbackTest {
  myCallback: Function;
}   

3

आप निम्नलिखित का उपयोग कर सकते हैं:

  1. उपनाम ( typeफ़ंक्शन शाब्दिक रूप से उपयोग करते हुए कीवर्ड)
  2. इंटरफेस
  3. समारोह शाब्दिक

उनका उपयोग कैसे किया जाए इसका एक उदाहरण इस प्रकार है:

type myCallbackType = (arg1: string, arg2: boolean) => number;

interface myCallbackInterface { (arg1: string, arg2: boolean): number };

class CallbackTest
{
    // ...

    public myCallback2: myCallbackType;
    public myCallback3: myCallbackInterface;
    public myCallback1: (arg1: string, arg2: boolean) => number;

    // ...

}

1

इवेंट श्रोता में कॉलबैक जोड़ने का प्रयास करते समय मैं एक ही त्रुटि पर आया था। अजीब बात है, EventListener को कॉलबैक प्रकार की स्थापना ने इसे हल किया। यह पूरे फ़ंक्शन हस्ताक्षर को एक प्रकार के रूप में परिभाषित करने से अधिक सुरुचिपूर्ण दिखता है, लेकिन मुझे यकीन नहीं है कि यह ऐसा करने का सही तरीका है।

class driving {
    // the answer from this post - this works
    // private callback: () => void; 

    // this also works!
    private callback:EventListener;

    constructor(){
        this.callback = () => this.startJump();
        window.addEventListener("keydown", this.callback);
    }

    startJump():void {
        console.log("jump!");
        window.removeEventListener("keydown", this.callback);
    }
}

पसंद है। लेकिन कार्रवाई में अन्य वर्ग कहां है?
यारो

1

मुझे थोड़ी देर हो गई है, लेकिन, टाइपस्क्रिप्ट में कुछ समय पहले से आप कॉलबैक के प्रकार को परिभाषित कर सकते हैं

type MyCallback = (KeyboardEvent) => void;

उपयोग का उदाहरण:

this.addEvent(document, "keydown", (e) => {
    if (e.keyCode === 1) {
      e.preventDefault();
    }
});

addEvent(element, eventName, callback: MyCallback) {
    element.addEventListener(eventName, callback, false);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.