Function Overload di Typescript
Misal kita ingin membuat function combine
untuk menggabungkan dua buah string atau array
Keliahatannya oke, tapi tidak dengan
Lho kenapa ada tanda komanya? Harusnya kan 'jihadwaspadaganteng'
? Entahlah. Mungkin ini salah satu keajaiban javascript. Tapi yang pasti kita nggak pingin dong kodenya menghasilkan sesuatu yang tidak reliable (tidak intuitif, tidak sesuai ekspektasi).
Untuk memperbaikinya mungkin bisa kita batasi requirement fungsi combine
dimana:
- Jika argument pertamanya berupa string, argument keduanya juga harus string. Return type-nya juga string
- Jika argument pertamanya berbentuk array, argument keduanya juga harus array. Return type-nya juga array
Di luar kombinasi ini—seperti combine('jihad', ['waspada'])
atau combine(['jihad'], 'waspada')
—harus error, nggak typecheck. Lalu gimana cara mengekspresikan requirement ini dengan Typescript?
Kita coba dulu pake union biasa:
Hmm error. Di sini typechecker berusaha melakukan unifikasi string
dengan T[]
di posisi contravariant (parameter method concat
) menghasilkan (T | combineArray<T>) & string
tapi gak typecheck ketika dikasih argument berupa string. Penjelasan lebih detailnya dibahas di artikel ini. Tapi bukan itu masalah utamanya.
Masalahnya utamanya, type signature fungsi combine
masih ill-typed sekalipun implementasinya typecheck:
Kode di atas seharusnya error tapi malah typecheck. Lha terus piye?
Kita ingin membuat asosiasi type di function parameter dengan return type-nya. Dan di sinilah fitur function overload Typescript berguna! Type signature-nya pun cukup ekspresif:
Kita hanya perlu menuliskan type annotations di posisi parameter dan return untuk melakukan function overload, tak perlu function body. Typechecker akan meng-evaluasi overload yang paling atas dulu dan akan lanjut ke overload di baris selanjutnya bila yang pertama tadi gak cocok. Begitupun seterusnya sampai mentok di overload terakhir. Untuk type annotation di function implementation-nya sendiri, cukup kita definisikan dengan type yang kompatibel dengan semua overload-nya: dalam kasus ini saya pilih any
biar gampang.
Oleh karena itu ketika menuliskan function overload, type yang paling spesifik sebaiknya diletakkkan di baris teratas.
Dan ketika kita check:
Naiiss 🔥
Saya punya contoh lain: anggap kita ingin membuat fungsi findElem
, mirip-mirip dengan Array.find
tapi return type-nya bisa dikonfigurasi jika item yang dicari tidak ditemukan. Ada 3 konfigurasi:
- Mengembalikan undefined
- Mengembalikan error message
- Mengembalikan default value
Dengan konfigurasi ini, kita bisa membuat fungsi findElem
seperti berikut:
Sama seperti fungsi combine
di pembahasan sebelumnya dimana return type-nya bergantung kepada type di kedua buah parameter-nya, return type fungsi findElem
bergantung kepada type Config
yang disuplai.
Menyuplainya dengan config yang tak ada di-definisi overload menyebabkan error:
Saya harap artikel ini bermanfaat.