Menu

Function Type TypeScript: Sintaks Arrow dan Tipe Callback

Cara menulis tipe sebuah fungsi di TypeScript: sintaks arrow (a: number) => string, type alias untuk fungsi, memberi tipe pada arrow function dan callback, call signature dan construct signature, serta kenapa tipe Function terlalu longgar.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Function type mendeskripsikan parameter dan nilai kembalian sebuah fungsi, ditulis dengan panah: (a: number, b: number) => number. Beri nama dengan type, dan kamu bisa memakainya untuk variabel, parameter, dan property objek.

Fungsi yang diberikan ke add tidak butuh anotasi: tipe parameternya berasal dari Operation. Ini disebut contextual typing, dan itulah alasan utama untuk memberi nama pada function type.

Sintaks Function Type

Bentuknya adalah (parameters) => ReturnType. Setiap parameter butuh nama dan tipe. Nama-nama itu ada demi keterbacaan dan petunjuk di editor; fungsi apa pun dengan tipe parameter yang kompatibel akan cocok, apa pun nama parameternya.

type Predicate = (value: number) => boolean;
type Formatter = (value: number, digits?: number) => string; // optional parameter
type Logger = (...parts: string[]) => void;                    // rest parameter
type Factory = () => { id: number };                           // no parameters

Namanya tidak opsional. (string) => void mendeklarasikan parameter bernama string tanpa tipe, dan strict mode menolaknya dengan TS7051: Parameter has a name but no type. Did you mean 'arg0: string'?. Tulis (value: string) => void.

Memberi Tipe pada Arrow Function

Arrow function bisa diberi tipe dengan dua cara. Beri anotasi pada fungsinya, atau beri anotasi function type pada variabelnya dan biarkan parameternya disimpulkan.

Bentuk 1 adalah pilihan yang biasa untuk fungsi yang berdiri sendiri. Bentuk 3 berguna ketika beberapa fungsi berbagi satu signature (handler, comparator, converter), karena signature-nya cukup ditulis sekali dan perubahan padanya diperiksa di mana-mana.

Tipe Callback

Parameter yang tipenya function type adalah callback. Fungsi dari pemanggil diperiksa terhadap tipe itu, dan parameternya disimpulkan dari tipe tersebut.

Ada dua aturan yang membuat callback nyaman dipakai:

  • Parameter yang lebih sedikit tidak masalah. Fungsi yang menerima satu parameter boleh dikirim ke tempat yang menawarkan dua. JavaScript mengabaikan argumen tambahan, jadi TypeScript mengizinkannya. Parameter yang lebih banyak daripada yang ditawarkan tipenya adalah error (Target signature provides too few arguments.).
  • Tipe kembalian void menerima apa saja. Callback bertipe (...) => void boleh mengembalikan nilai; pemanggil berjanji tidak memakainya. Itulah sebabnya list.forEach((x) => other.push(x)) bisa dikompilasi meskipun push mengembalikan angka.

Tipe parameternya tetap harus kompatibel. Mengirim (x: string) => ... ke tempat yang mengharapkan (a: number, b: number) => number gagal dengan Types of parameters 'x' and 'a' are incompatible.

Call Signature

(n: number) => string adalah singkatan dari object type dengan call signature: { (n: number): string }. Kamu butuh bentuk panjangnya ketika fungsi itu juga membawa property.

TypeScript membolehkanmu menambahkan property ke fungsi yang dideklarasikan dengan const di scope yang sama, dan melacaknya di tipe fungsi itu. Interface juga bisa memuat call signature: interface Counter { (): number; count: number }.

Construct signature mendeskripsikan sesuatu yang dipanggil dengan new. Bentuknya menambahkan new di depan: new (name: string) => User, atau { new (name: string): User } dalam bentuk objek. Begitulah cara memberi tipe pada parameter yang menerima sebuah class.

Sintaks Method vs Sintaks Property

Di sebuah object type, member berupa fungsi bisa ditulis sebagai method, handle(value: string): void, atau sebagai property yang berisi fungsi, handle: (value: string) => void. Keduanya terlihat bisa saling menggantikan, tetapi diperiksa secara berbeda dengan strict:

Compiler melaporkan:

index.ts(8,27): error TS2322: Type '(value: string) => void' is not assignable to type '(value: string | number) => void'.
  Types of parameters 'value' and 'value' are incompatible.
    Type 'string | number' is not assignable to type 'string'.
      Type 'number' is not assignable to type 'string'.

Error itu benar: onlyStrings tidak bisa menangani angka. Bentuk method meloloskan kesalahan yang sama (parameter method diperiksa secara "bivariant" karena alasan historis), dan a.handle(42) akan crash saat runtime dengan TypeError: value.toUpperCase is not a function. Hapus baris b untuk melihat crash itu. Saat kamu menulis object type sendiri, bentuk property menangkap lebih banyak kesalahan.

Hindari Tipe Function

Function adalah tipe bawaan yang dipenuhi oleh setiap nilai fungsi. Tipe ini hampir tidak pernah yang kamu inginkan: TypeScript tidak tahu parameter maupun tipe kembaliannya, jadi setiap pemanggilan diterima dan mengembalikan any.

Ganti Function dengan signature yang sebenarnya. Kalau kamu memang menerima fungsi apa pun (debounce generic, wrapper untuk logging), (...args: never[]) => unknown menerima setiap fungsi dan tetap menjaga hasilnya bertipe unknown, bukan any. Untuk fungsi yang tipenya bergantung pada input-nya, lihat generic: function type generic bentuknya seperti <T>(value: T) => T.

Pertanyaan yang sering diajukan

Bagaimana cara mendefinisikan function type di TypeScript?

Pakai sintaks arrow: (a: number, b: number) => number. Beri nama dengan type alias, type Compare = (a: number, b: number) => number;, lalu pakai nama itu untuk variabel, parameter, dan property. Nama parameter adalah bagian dari sintaks, tetapi hanya untuk dokumentasi: fungsi dengan nama parameter yang berbeda tetap cocok.

Bagaimana cara memberi tipe pada parameter callback di TypeScript?

Tulis function type sebagai tipe parameternya: function onEach(items: string[], cb: (item: string, index: number) => void) { ... }. Pemanggil boleh mengirim fungsi yang menerima parameter lebih sedikit, dan parameter callback itu sendiri disimpulkan dari tipe tersebut, jadi onEach(list, (item) => ...) tidak butuh anotasi.

Kenapa sebaiknya aku tidak memakai tipe Function di TypeScript?

Function menerima fungsi apa pun dan pemanggilannya tidak diperiksa: argumen apa pun diizinkan dan hasilnya any. Tulis signature yang sebenarnya, seperti () => void atau (value: string) => number, atau (...args: never[]) => unknown kalau kamu memang menerima semua fungsi.

Apa bedanya function type dan call signature?

Keduanya mendeskripsikan hal yang sama. (n: number) => string adalah singkatan dari object type { (n: number): string }. Bentuk call signature dibutuhkan ketika fungsi itu juga punya property, misalnya { (n: number): string; label: string }.

Bagaimana cara memberi tipe pada arrow function di TypeScript?

Beri anotasi langsung pada parameter dan tipe kembaliannya, const half = (n: number): number => n / 2;, atau beri variabel itu function type dan biarkan parameternya disimpulkan: const half: (n: number) => number = (n) => n / 2;.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai