Generic dengan Constraint
Membatasi generic dengan extends supaya method yang dipakai dijamin ada.
Generic Terlalu Bebas Itu Masalah
function cetakPanjang<T>(nilai: T): void {
console.log(nilai.length);
// Error: Property 'length' does not exist on type 'T'.
}Karena T bisa apa saja, compiler melarang akses .length. Masuk akal: bagaimana kalau T-nya number?
Constraint dengan extends
function cetakPanjang<T extends { length: number }>(nilai: T): void {
console.log(nilai.length); // ok, T dijamin punya .length
}
cetakPanjang("halo"); // ok, string punya length
cetakPanjang([1, 2, 3]); // ok, array punya length
cetakPanjang(123); // Error: number tidak punya lengthextends di sini bukan pewarisan class, melainkan syarat: "T harus punya minimal bentuk ini". Fleksibilitas generic tetap ada, tapi dengan pagar pengaman.
Constraint Praktis: Objek dengan ID
interface PunyaId {
id: string | number;
}
function ambilId<T extends PunyaId>(item: T): string | number {
return item.id;
}
ambilId({ id: 1, nama: "Ana" }); // ok
ambilId({ nama: "Ana" }); // Error: tidak punya idPola ini muncul di mana-mana: fungsi utilitas yang bekerja untuk "object apa pun asal punya field tertentu".
Constraint antar Type Parameter
Generic juga bisa dibatasi oleh generic lain:
function ambilProperti<T, K extends keyof T>(obj: T, kunci: K): T[K] {
return obj[kunci];
}
const user = { nama: "Ana", umur: 17 };
ambilProperti(user, "nama"); // ok, bertipe string
ambilProperti(user, "alamat"); // Error: "alamat" bukan keyof userK extends keyof T menjamin kunci yang diminta benar-benar ada di object. Akses properti dinamis yang biasanya rawan typo jadi aman total.
Catatan teknis: Constraint adalah batas bawah kemampuan, bukan batas atas.
T extends { length: number }menerima object apa pun yang punyalength, tidak harus persis bentuk itu. Jangan terkecoh mengira T "sama dengan" constraint-nya; T tetap tipe spesifik yang diteruskan pemanggil.