Daktilo Yazısı: Yöntem parametresinde kullanılan işlev geri araması için tür tanımlanır (herhangi bir işlev türü olarak, evrensel değil)


313

Şu anda türü tanımı var:

interface Param {
    title: string;
    callback: any;
}

Gibi bir şeye ihtiyacım var:

interface Param {
    title: string;
    callback: function;
}

ama ikincisi kabul edilmiyor.

Yanıtlar:


285

Global tip Functionbu amaca hizmet eder.

Ayrıca, bu geri aramayı 0 bağımsız değişkeniyle çağırmak ve dönüş değerini yoksayarsanız, tür () => voidbağımsız değişken almayan tüm işlevlerle eşleşir.



13
Bu temel bir tür değildir çünkü argümanlarınızı ve dönüş değerlerinizi tanımlamanız gerekir. geri arama gibi bir şey: (sayı: sayı) => geçersiz; tür denetimi için geri aramadan daha yararlıdır: function; olabilir.
kpup

Açık olmak gerekirse @kpup, demek değil kullanım sermaye F Functionbu cevabın ilk satırda gösterildiği gibi, ikinci paragraf söyleyerek (tipini kullanarak () => voidtercih edilir veya kullanma durumu uyan neyse)?
ruffin

2
FWIW, fonksiyon türlerinde dosyaları kullanıma sunuldu burada
imjared

191

V1.4'ten gelen daktiloda, typebir tür takma adı bildiren bir anahtar kelime bulunur ( typedefC / C ++ 'da a'ya benzer ). Geri arama türünüzü şu şekilde beyan edebilirsiniz:

type CallbackFunction = () => void;

hiçbir argüman almayan ve hiçbir şey döndürmeyen bir işlevi bildirir. Herhangi bir türden sıfır veya daha fazla argüman alan ve hiçbir şey döndürmeyen bir işlev şöyle olur:

type CallbackFunctionVariadic = (...args: any[]) => void;

O zaman, örneğin,

let callback: CallbackFunctionVariadic = function(...args: any[]) {
  // do some stuff
};

Rastgele sayıda argüman alan ve bir şey döndüren (void dahil) bir işlev istiyorsanız:

type CallbackFunctionVariadicAnyReturn = (...args: any[]) => any;

Bazı zorunlu argümanları ve ardından bir dizi ek argüman belirtebilirsiniz (dize, sayı ve sonra bir dizi ekstra argüman söyleyin):

type CallbackFunctionSomeVariadic =
  (arg1: string, arg2: number, ...args: any[]) => void;

Bu, EventEmitter işleyicileri gibi şeyler için yararlı olabilir.

İşlevler bu şekilde istediğiniz kadar güçlü bir şekilde yazılabilir, ancak her şeyi bir tür takma adla çivilemeye çalışırsanız, taşınabilir ve birleştirici problemlerle karşılaşabilirsiniz.


1
Arasında Functionve (...args: any[]) => anyne tercih edilir?
ahong

@ahong: Şahsen ikincisini bir imza sağladığı için tercih ederim ... normalde. ...args: any[]çok kullanışlı değil.
Ed

type CallbackFunctionSomeVariadic = (arg1: string, arg2: number, ...args: any[]) => void;aradığım şey, ty.
aqteifan

61

Ryan'ın cevabından sonra, aradığınız arayüzün aşağıdaki gibi tanımlandığını düşünüyorum:

interface Param {
    title: string;
    callback: () => void;
}

34

Aşağıda, geri aramayı kabul eden bir işlev örneği verilmiştir

const sqk = (x: number, callback: ((_: number) => number)): number => {
  // callback will receive a number and expected to return a number
  return callback (x * x);
}

// here our callback will receive a number
sqk(5, function(x) {
  console.log(x); // 25
  return x;       // we must return a number here
});

Geri aramaların dönüş değerlerini umursamıyorsanız (çoğu kişi bunları etkili bir şekilde nasıl kullanacağını bilmez), void

const sqk = (x: number, callback: ((_: number) => void)): void => {
  // callback will receive a number, we don't care what it returns
  callback (x * x);
}

// here our callback will receive a number
sqk(5, function(x) {
  console.log(x); // 25
  // void
});

Not, callbackparametre için kullandığım imza ...

const sqk = (x: number, callback: ((_: number) => number)): number

Geri arama parametreleri için bir ad sağlamamız bekleniyor, çünkü bu bir TypeScript eksikliği olduğunu söyleyebilirim . Bu durumda kullandım _çünkü sqkfonksiyon içinde kullanılabilir değil .

Ancak, bunu yaparsanız

// danger!! don't do this
const sqk = (x: number, callback: ((number) => number)): number

Bu var geçerli typescript ama olarak yorumlanır olacak ...

// watch out! typescript will think it means ...
const sqk = (x: number, callback: ((number: any) => number)): number

Yani, typescript parametre düşünecek adı olan numberzımni tipi ve olduğunu any. Açıkçası bizim istediğimiz bu değil, ne yazık ki, TypeScript böyle çalışır.

Bu nedenle, işlev parametrelerinizi yazarken parametre adlarını vermeyi unutmayın ... göründüğü gibi aptalca.


32

Arayüzde bir işlev türünü çeşitli şekillerde tanımlayabilirsiniz,

  1. genel yol:
export interface IParam {
  title: string;
  callback(arg1: number, arg2: number): number;
}
  1. Özellik sözdizimini kullanmak istiyorsanız,
export interface IParam {
  title: string;
  callback: (arg1: number, arg2: number) => number;
}
  1. Önce işlev türünü bildirirseniz,
type MyFnType = (arg1: number, arg2: number) => number;

export interface IParam {
  title: string;
  callback: MyFnType;
}

Kullanımı çok basit,

function callingFn(paramInfo: IParam):number {
    let needToCall = true;
    let result = 0;
   if(needToCall){
     result = paramInfo.callback(1,2);
    }

    return result;
}
  1. Bir işlev türü değişmezi de bildirebilirsiniz; bu, bir işlevin parametre olarak başka bir işlevi kabul edebileceği anlamına gelir. Parametreleme işlevi geri arama olarak da adlandırılabilir.
export interface IParam{
  title: string;
  callback(lateCallFn?:
             (arg1:number,arg2:number)=>number):number;

}

10

Dört soyut işlev türü vardır, işlevinizin bağımsız değişken (ler) alıp almayacağını, veri döndürüp döndürmeyeceğini bildiğinizde bunları ayrı olarak kullanabilirsiniz.

export declare type fEmptyVoid = () => void;
export declare type fEmptyReturn = () => any;
export declare type fArgVoid = (...args: any[]) => void;
export declare type fArgReturn = (...args: any[]) => any;

bunun gibi:

public isValid: fEmptyReturn = (): boolean => true;
public setStatus: fArgVoid = (status: boolean): void => this.status = status;

Herhangi bir işlev türü olarak yalnızca bir tür kullanmak için, tüm soyut türleri bir araya getirebiliriz, örneğin:

export declare type fFunction = fEmptyVoid | fEmptyReturn | fArgVoid | fArgReturn;

sonra şöyle kullanın:

public isValid: fFunction = (): boolean => true;
public setStatus: fFunction = (status: boolean): void => this.status = status;

Yukarıdaki örnekte her şey doğrudur. Ancak feryattaki kullanım örneği, çoğu kod düzenleyicisinin bakış açısından doğru değildir.

// you can call this function with any type of function as argument
public callArgument(callback: fFunction) {

    // but you will get editor error if call callback argument like this
    callback();
}

Editörler için doğru çağrı şöyledir:

public callArgument(callback: fFunction) {

    // pay attention in this part, for fix editor(s) error
    (callback as fFunction)();
}

2

Typescript: nasıl kullanılan bir işlev geri arama için türünü tanımlamak için bir yöntem parametresi?

Geri aramayı 1) function özelliği veya 2) yöntemi olarak bildirebilirsiniz :

interface ParamFnProp {
    callback: (a: Animal) => void; // function property
}

interface ParamMethod {
    callback(a: Animal): void; // method
}

TS 2.6'dan beri önemli bir yazma farkı var :

Bir function özelliği bildirildiğinde daha güçlü ("ses") türlerini --strictveya --strictFunctionTypeskipini alırsınız . Bir örnek verelim:

const animalCallback = (a: Animal): void => { } // Animal is the base type for Dog
const dogCallback = (d: Dog): void => { } 
// function property variant
const param11: ParamFnProp = { callback: dogCallback } // error: not assignable
const param12: ParamFnProp = { callback: animalCallback } // works

// method variant
const param2: ParamMethod = { callback: dogCallback } // now it works again ...

Teknik diller, yöntemler bivariant ve fonksiyon özellikleri kontravaryant altında argümanlar strictFunctionTypes. Yöntemler, daha yerleşik (tip olmasa bile) gibi yerleşik tiplerle birlikte biraz daha pratik olmak için daha izinli olarak kontrol edilirArray .

özet

  • İşlev özelliği ile yöntem bildirimi arasında bir tür farkı vardır
  • Mümkünse daha güçlü türler için bir işlev özelliği seçin

Oyun alanı örnek kodu

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.