Function Overload
Satu fungsi, banyak tanda tangan: overload untuk API yang fleksibel tapi tetap aman.
Analogi: Resepsionis Multibahasa
Resepsionis hotel melayani tamu lokal dengan bahasa Indonesia dan tamu asing dengan bahasa Inggris. Orangnya satu, tapi "prosedur pelayanannya" beda tergantung siapa yang datang, dan hasilnya selalu jelas: tamu terlayani dengan benar. Function overload seperti itu: satu fungsi, beberapa "tanda tangan" pemakaian, masing-masing dengan janji input-output yang presisi.
Masalah: Return Type Jadi Kabur
Tanpa overload, fungsi fleksibel terpaksa memakai union yang mengaburkan informasi:
function format(input: string | number): string | number {
return typeof input === "number" ? input.toFixed(2) : input.toUpperCase();
}
const hasil = format(3.14159); // tipenya string | number, padahal pasti string
hasil.toFixed(2); // Error: Property 'toFixed' does not exist on type 'string'.Pemanggil tahu inputnya number sehingga output pasti string, tapi compiler tidak tahu. Informasi presisi itu hilang di union.
Solusi: Tulis Signature-nya Satu per Satu
function format(input: number): string;
function format(input: string): string;
function format(input: string | number): string {
if (typeof input === "number") return input.toFixed(2);
return input.toUpperCase();
}
const a = format(3.14159); // string, presisi!
const b = format("2024-01-01"); // string
a.toUpperCase(); // OK, compiler tahu ini stringDua baris pertama adalah overload signature (tanpa badan), baris ketiga adalah implementasi yang tidak terlihat oleh pemanggil. Pemanggil hanya melihat signature yang cocok dengan argumennya.
Contoh error saat signature tidak cocok:
format(true);
// Error: No overload matches this call.
// Overload 1 of 2, '(input: number): string', gave the following error:
// Argument of type 'boolean' is not assignable to parameter of type 'number'.
// Overload 2 of 2, '(input: string): string', gave the following error:
// Argument of type 'boolean' is not assignable to parameter of type 'string'.Pesan errornya memang panjang, tapi justru informatif: dia menunjukkan semua signature yang dicoba dan kenapa masing-masing gagal.
Aturan Overload
- Signature overload ditulis tanpa badan fungsi.
- Implementasi (yang berbadan) tidak bisa dipanggil langsung dari luar, signature-nya tidak terlihat pemanggil.
- Urutan penting: yang lebih spesifik taruh lebih dulu, karena compiler mencoba dari atas ke bawah.
Kapan Dipakai di Project Nyata
- API library yang fleksibel:
createElement("div")vscreateElement(Component, props)di React, atau fungsi util yang menerima string atau array. - Fungsi dengan perilaku return berbeda tergantung tipe input, di mana union mengaburkan informasi.
- Jangan overuse: lebih dari 3-4 signature biasanya tanda fungsinya harus dipecah jadi beberapa fungsi atau memakai satu object parameter.
Catatan teknis: Implementasi harus kompatibel dengan semua signature. Kalau tidak, muncul error
This overload signature is not compatible with its implementation signature. Praktisnya: tipe parameter implementasi harus cukup longgar untuk menampung semua signature (biasanya union dari semuanya).
Tantangan
Overload konversi panjang
Buat fungsi panjang dengan overload: panjang(s: string): number (panjang string) dan panjang(arr: unknown[]): number (jumlah elemen). Implementasi menerima string | unknown[] dan mengembalikan .length.
function panjang(s: string): number;
function panjang(arr: unknown[]): number;
function panjang(input: string | unknown[]): number {
// lengkapi
}
console.log(panjang("halo")); // 4
console.log(panjang([1, 2, 3])); // 3