Naskah: Cara menentukan jenis untuk fungsi callback (sebagai jenis fungsi apa pun, bukan universal apa pun) yang digunakan dalam parameter metode


313

Saat ini saya memiliki definisi tipe sebagai:

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

Saya butuh sesuatu seperti:

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

tapi yang ke-2 tidak diterima.

Jawaban:


285

Tipe global Functionmelayani tujuan ini.

Selain itu, jika Anda bermaksud memohon callback ini dengan 0 argumen dan akan mengabaikan nilai pengembaliannya, tipe tersebut () => voidcocok dengan semua fungsi tanpa argumen.


27
benda ini hilang dalam tipe dasar
Yogesh

13
Ini bukan tipe dasar karena Anda harus mendefinisikan argumen dan mengembalikan nilai. sesuatu seperti callback: (number: number) => void; jauh lebih berguna untuk pengecekan tipe daripada callback: function; akan menjadi.
kpup

@ kpup Agar jelas, apakah Anda mengatakan tidak menggunakan Functionhuruf kapital F seperti yang ditunjukkan pada baris pertama dari jawaban ini, dan mengatakan paragraf kedua (menggunakan jenis () => voidatau apa pun yang cocok dengan use case) lebih disukai?
ruffin

2
FWIW, dokumen tentang tipe fungsi tersedia di sini
imjared

191

Naskah dari v1.4 memiliki typekata kunci yang menyatakan alias jenis (analog dengan a typedefdi C / C ++). Anda dapat mendeklarasikan jenis panggilan balik Anda sebagai berikut:

type CallbackFunction = () => void;

yang mendeklarasikan fungsi yang tidak menggunakan argumen dan tidak menghasilkan apa-apa. Fungsi yang tidak menggunakan argumen apa pun nol atau lebih dan tidak menghasilkan apa pun adalah:

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

Maka Anda dapat mengatakan, misalnya,

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

Jika Anda menginginkan fungsi yang mengambil sejumlah argumen sembarang dan mengembalikan apa pun (termasuk batal):

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

Anda dapat menentukan beberapa argumen wajib dan kemudian satu set argumen tambahan (katakanlah string, angka dan kemudian satu set argumen tambahan) dengan demikian:

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

Ini bisa berguna untuk hal-hal seperti penangan EventEmitter.

Fungsi dapat diketik sekuat yang Anda suka dalam mode ini, meskipun Anda dapat terbawa dan mengalami masalah kombinatorik jika Anda mencoba untuk memakukan semuanya dengan alias alias.


1
Antara Functiondan (...args: any[]) => anyapa yang lebih disukai?
ahong

@ Ahong: Secara pribadi saya lebih suka yang terakhir karena memberikan tanda tangan ... biasanya. ...args: any[]tidak terlalu berguna.
Ed S.

type CallbackFunctionSomeVariadic = (arg1: string, arg2: number, ...args: any[]) => void;apa yang saya cari, ty.
aqteifan

61

Mengikuti dari jawaban Ryan, saya pikir antarmuka yang Anda cari didefinisikan sebagai berikut:

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

34

Berikut adalah contoh fungsi yang menerima panggilan balik

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

Jika Anda tidak peduli dengan nilai balik callback (kebanyakan orang tidak tahu bagaimana menggunakannya dengan cara yang efektif), Anda dapat menggunakan 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
});

Catatan, tanda tangan yang saya gunakan untuk callbackparameter ...

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

Saya akan mengatakan ini adalah kekurangan TypeScript karena kami diharapkan untuk memberikan nama untuk parameter panggilan balik. Dalam hal ini saya menggunakan _karena tidak dapat digunakan di dalam sqkfungsi.

Namun, jika Anda melakukan ini

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

Ini TypeScript yang valid , tetapi akan ditafsirkan sebagai ...

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

Yaitu, naskah akan berpikir parameter nama adalah numberdan jenis tersirat adalah any. Ini jelas bukan yang kami maksudkan, tetapi sayangnya, itulah cara kerja TypeScript.

Jadi jangan lupa untuk memberikan nama parameter saat mengetik parameter fungsi Anda ... sepertinya bodoh.


32

Anda dapat menentukan jenis fungsi dalam antarmuka dengan berbagai cara,

  1. cara umum:
export interface IParam {
  title: string;
  callback(arg1: number, arg2: number): number;
}
  1. Jika Anda ingin menggunakan sintaksis properti,
export interface IParam {
  title: string;
  callback: (arg1: number, arg2: number) => number;
}
  1. Jika Anda mendeklarasikan jenis fungsi terlebih dahulu,
type MyFnType = (arg1: number, arg2: number) => number;

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

Menggunakan sangat lurus ke depan,

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

    return result;
}
  1. Anda dapat mendeklarasikan tipe fungsi literal juga, yang berarti suatu fungsi dapat menerima fungsi lain sebagai parameternya. fungsi parameterize dapat disebut sebagai callback juga.
export interface IParam{
  title: string;
  callback(lateCallFn?:
             (arg1:number,arg2:number)=>number):number;

}

10

Ada empat jenis fungsi abstrak, Anda dapat menggunakannya secara terpisah ketika Anda tahu fungsi Anda akan mengambil argumen (s) atau tidak, akan mengembalikan data atau tidak.

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

seperti ini:

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

Untuk hanya menggunakan satu tipe sebagai tipe fungsi apa pun, kami dapat menggabungkan semua tipe abstrak menjadi satu, seperti ini:

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

lalu gunakan seperti:

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

Dalam contoh di atas semuanya benar. Tetapi contoh penggunaan di bawah ini tidak benar dari sudut pandang sebagian besar editor kode.

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

Panggilan editor yang benar adalah seperti ini:

public callArgument(callback: fFunction) {

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

2

Naskah: Bagaimana menentukan jenis untuk fungsi callback yang digunakan dalam parameter metode ?

Anda dapat mendeklarasikan callback sebagai 1) fungsi properti atau 2) metode :

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

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

Ada perbedaan pengetikan yang penting sejak TS 2.6 :

Anda mendapatkan lebih kuat ("suara") ketik --strictatau --strictFunctionTypesmode, ketika properti fungsi dideklarasikan. Mari kita ambil contoh:

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 ...

Secara teknis, metode bersifat bivarian dan berfungsi sebagai contravarian dalam argumen mereka strictFunctionTypes. Metode masih diperiksa lebih permisif (bahkan jika tidak suara) menjadi sedikit lebih praktis dalam kombinasi dengan tipe bawaan seperti Array.

Ringkasan

  • Ada perbedaan jenis antara properti fungsi dan deklarasi metode
  • Pilih properti fungsi untuk tipe yang lebih kuat, jika memungkinkan

Kode sampel taman bermain

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.