Function Overloads — TypeScript

Kadang sebuah fungsi benar-benar menerima bentuk parameter yang berbeda. Contoh: formatTanggal(new Date()) atau formatTanggal("2024-01-03"). Satu union type…

Function overload artinya satu fungsi punya beberapa signature: pasangan "kalau yang masuk ini, yang keluar itu". Signature adalah satu baris berisi nama fungsi, tipe parameter, dan tipe return-nya, tanpa isi. Mirip papan menu di warung: "pesan satu nomor, dapat satu piring; pesan beberapa nomor, dapat satu nampan". Pembeli cuma membaca papan menunya. Dapur yang benar-benar memasak gak kelihatan dari luar.

🧪 Tebakan cepat: fungsi pesan menerima number | number[] dan mengembalikan string | string[]. Kamu memanggil pesan(0), lalu .toUpperCase() pada hasilnya. TypeScript mengizinkan atau menolak? Tebak dulu, jawabannya ada di bagian "Masalah kalau cuma pakai union".

Masalah kalau cuma pakai union

Warung kita punya tiga menu. Nomor menunya adalah index array, jadi 0 itu Kopi dan 2 itu Roti.

const MENU = ["Kopi", "Teh", "Roti"];

function pesan(nomor: number | number[]): string | string[] {
  if (Array.isArray(nomor)) {
    return nomor.map((n) => MENU[n]); // daftar nomor, daftar nama
  }
  return MENU[nomor]; // satu nomor, satu nama
}

const hasil = pesan(0); // hasil: string | string[]
hasil.toUpperCase();
error TS2339: Property 'toUpperCase' does not exist on type 'string | string[]'.
  Property 'toUpperCase' does not exist on type 'string[]'.

TypeScript menolak. Itu jawaban tebakannya. Kamu tahu pesan(0) pasti mengembalikan satu teks, tapi tipenya cuma bilang "string atau array string". Array gak punya .toUpperCase(), jadi TypeScript gak mau ambil risiko. Informasi "satu masuk, satu keluar" hilang di union.

Menulis overload

Overload mengembalikan informasi itu. Tulis dulu signature untuk pemanggil, lalu satu implementasi di paling bawah:

const MENU = ["Kopi", "Teh", "Roti"];

// Overload signature: untuk pemanggil, tanpa isi
function pesan(nomor: number): string;
function pesan(nomor: number[]): string[];
// Implementasi: satu-satunya yang punya isi
function pesan(nomor: number | number[]): string | string[] {
  if (Array.isArray(nomor)) {
    return nomor.map((n) => MENU[n]);
  }
  return MENU[nomor];
}

const satu = pesan(0);     // satu: string
const dua = pesan([0, 2]); // dua: string[]
satu.toUpperCase();        // "KOPI", sekarang boleh
dua.join(", ");            // "Kopi, Roti"
Panggilan Overload yang cocok Tipe hasil Nilai saat jalan
pesan(0) (nomor: number): string string "Kopi"
pesan([0, 2]) (nomor: number[]): string[] string[] ["Kopi", "Roti"]
pesan("0") gak ada error ditolak sebelum jalan
error TS2769: No overload matches this call.
  The last overload gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'number[]'.

Setelah di-compile, overload signature hilang semua. JavaScript cuma punya satu fungsi pesan, yaitu implementasinya. Overload murni urusan pengecekan tipe.

Aturan menulisnya

Kapan union saja sudah cukup

Overload berguna kalau tipe hasilnya bergantung pada tipe input: satu nomor jadi satu teks, daftar nomor jadi daftar teks. Kalau hasilnya selalu sama apa pun inputnya, union biasa sudah cukup dan lebih ringkas:

function panjang(isi: string | number[]): number {
  return isi.length; // string dan array sama-sama punya length
}

panjang("halo");    // 4
panjang([1, 2, 3]); // 3

Output-nya selalu number, jadi gak ada informasi yang hilang. Patokannya: output beda per tipe input, pakai overload. Output sama untuk semua input, pakai union.

⚠️ Jebakan yang sering ketemu

TL;DR: Function overload memberi satu fungsi beberapa signature, supaya tipe hasilnya ikut tipe input: pesan(0) bertipe string, pesan([0, 2]) bertipe string[]. Tulis semua overload signature dulu (tanpa isi, diakhiri titik koma), lalu satu implementasi di paling bawah yang tipenya mencakup semuanya. Pemanggil cuma melihat overload, bukan implementasi, dan TypeScript memakai overload pertama yang cocok, jadi yang spesifik di atas. Setelah compile, overload hilang. Kalau output-nya sama untuk semua input, union biasa sudah cukup.

Yang akan kamu pelajari