TypeScript geri arama türünü tanımlama


173

TypeScript'te şu sınıfı aldım:

class CallbackTest
{
    public myCallback;

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

Sınıfı şu şekilde kullanıyorum:

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

Kod çalışır, bu nedenle beklendiği gibi bir mesaj kutusu görüntüler.

Sorum şu: Sınıf alanım için sağlayabileceğim herhangi bir tür var mı myCallback? Şu anda, kamu alanı myCallbacktiptedir anyyukarıda gösterildiği gibi. Geri aramanın yöntem imzasını nasıl tanımlayabilirim? Yoksa türü bir tür geri arama türüne ayarlayabilir miyim? Yoksa bunlardan daha net yapabilir miyim? Kullanmam gerekiyor anymu (örtük / açık)?

Böyle bir şey denedim, ama işe yaramadı (derleme zamanı hatası):

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

Bu konuda çevrimiçi bir açıklama bulamadım, umarım bana yardımcı olabilirsiniz.

Yanıtlar:


212

Sadece TypeScript dil spesifikasyonunda bir şey buldum, oldukça kolay. Oldukça yakındım.

sözdizimi aşağıdaki gibidir:

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

Örneğimde,

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

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

8
Geri arama imzasını tanımlamak için parametre adının neden gerekli olduğunu
anlamıyorum

4
Sanırım C # ekibinden bazı kültürel miraslar olabilir, sanırım sonuçta hoşuma gitti ...
2grit

@nikeee belgelerin bu sayfasına bir link verebilir misiniz?
jcairney


148

Bir adım daha ileri gitmek için, aşağıdaki gibi bir işlev imzasına bir tür işaretçisi bildirebilirsiniz:

interface myCallbackType { (myArgument: string): void }

ve şu şekilde kullanın:

public myCallback : myCallbackType;

9
Bu, (IMO) kabul edilen yanıttan çok daha iyi bir çözümdür, çünkü bir tür tanımlamanıza ve daha sonra, bu tür bir parametreyi (geri arama) iletmenize izin verir, daha sonra onu aramak da dahil olmak üzere istediğiniz şekilde kullanabilirsiniz. Kabul edilen cevap bir üye değişkeni kullanır ve üye değişkeni işlevinize ayarlamanız ve sonra çirkin ve hatalara eğilimli bir yöntem çağırmanız gerekir, çünkü değişkenin ilk olarak ayarlanması yöntemi çağırma sözleşmesinin bir parçasıdır.
David

Ayrıca, geri aramayı nullable olarak kolayca ayarlamanızı sağlar, örn.let callback: myCallbackType|null = null;
Doches

1
TSLint'in "TSLint: Arayüzde yalnızca bir çağrı imzası var - type MyHandler = (myArgument: string) => voidbunun yerine kullanın. ( Çağrılabilir türler)" ;
TSV'nin

Bu cevabın ilk taslağı beni bu soruya götüren problemi çözdü. Bir derleyici hatası üretmeden herhangi bir sayıda parametre kabul edebilen bir arabirim içinde yeterli bir izin imzası tanımlamak çalışıyordu. Benim durumumdaki cevap kullanmaktı ...args: any[]. Örnek: export interface MyInterface {/ ** Geri arama işlevi. / callback: (... args: any []) => any, / * Geri arama işlevi için parametreler. Plajlar: any []}
Ken Lyon

62

Yeni bir tür bildirebilirsiniz:

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

var handler: MyHandler;

Güncelleme.

declareAnahtar kelime gerekli değildir. .D.ts dosyalarında veya benzer durumlarda kullanılmalıdır.


Bunun için belgeleri nerede bulabilirim?
E. Sundin


1
Doğru ve bilmek güzel olsa da, aynı sayfada (günümüzde) "Yazılımın ideal bir özelliği uzantıya açık olduğu için, mümkünse her zaman tür takma adı üzerinde bir arabirim kullanmanız gerekir."
Arjan

@Arjan - Nesneler için buna tamamen katılıyorum. Lütfen belirtebilir misiniz - bir işlevi nasıl genişletmek istersiniz?
TSV

Tür bildiriminin isteğe bağlı olduğunu unutmayın: var handler: (myArgument: string) => voidsözdizimsel olarak geçerlidir (biraz dağınıksa).
Hutch

36

İşte bir örnek - parametre kabul etmemek ve hiçbir şey döndürmemek.

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();

Bir parametreyi kabul etmek istiyorsanız, bunu da ekleyebilirsiniz:

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

Ve bir değer döndürmek istiyorsanız, bunu da ekleyebilirsiniz:

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

İşlevsel olarak aynıdırlar - aynı şeyi tanımlarlar ve işlev imzası üzerinde yazım denetimi yaparlar. Hangisini tercih ederseniz kullanabilirsiniz. Spesifikasyon olduklarını söylüyor exactly equivalent.
Fenton

6
@nikeee: Soru, cevabınızla farklı olan nedir? Steve cevabını sizinkinden önce gönderdi.
jgauffin

@jgauffin Gerçekten de sonuç aynı. Steve'in sürümü tüm arayüz tanımlarına izin verdiğinden, IMO gönderdiğim çözüm geri çağrılar hakkında konuşurken daha doğal. Tercihinize bağlıdır.
nikeee

@Fenton bu belgelere bir bağlantı verebilir misiniz lütfen?
jcairney

18

Genel bir işlev istiyorsanız, aşağıdakileri kullanabilirsiniz. Her ne kadar hiçbir yerde belgelenmemiş gibi görünüyor.

class CallbackTest {
  myCallback: Function;
}   

4

Aşağıdakileri kullanabilirsiniz:

  1. Diğer Ad yazın ( typeanahtar sözcüğü kullanarak , bir işlev değişmezini takma)
  2. Arayüz
  3. İşlev Değişmezi

Bunların nasıl kullanılacağına dair bir örnek:

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;

    // ...

}

2

Bir olay dinleyicisine geri arama eklemeye çalışırken aynı hatayla karşılaştım. Garip bir şekilde, geri arama türünü EventListener olarak ayarlamak sorunu çözdü. Tüm işlev imzasını bir tür olarak tanımlamaktan daha zarif görünüyor, ancak bunun doğru yolu olup olmadığından emin değilim.

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);
    }
}

gibi. Peki diğer sınıf nerededir?
Yaro

2

Biraz geç kaldım, ancak TypeScript'te bir süre önce geri arama türünü tanımlayabilirsiniz.

type MyCallback = (KeyboardEvent) => void;

Kullanım örneği:

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

addEvent(element, eventName, callback: MyCallback) {
    element.addEventListener(eventName, callback, false);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.