Panduan Praktis TypeScript Generics untuk Kode yang Reusable
Apa itu TypeScript Generics?
Generics adalah salah satu fitur paling kuat di TypeScript. Fitur ini memungkinkan kita untuk membuat komponen kode (seperti fungsi, kelas, atau interface) yang dapat bekerja dengan berbagai tipe data, namun tetap menjaga akurasi tipe data tersebut (type safety).
Tanpa Generics, kita mungkin tergoda untuk menggunakan tipe any. Namun, penggunaan any merusak tujuan utama dari penggunaan TypeScript karena compiler tidak dapat melacak tipe data asli kita.
Mengapa Kita Membutuhkan Generics?
Bayangkan Anda ingin membuat fungsi sederhana yang mengembalikan elemen pertama dari sebuah array.
function dapatkanElemenPertama(arr: any[]): any {return arr[0];}
Fungsi di atas bekerja, tetapi tipe kembaliannya adalah any. Jika kita memasukkan array berisi string, compiler tidak akan tahu bahwa hasil kembaliannya adalah string. Di sinilah Generics masuk menyelamatkan hari!
Dengan Generics, kita mendefinisikan sebuah "variabel tipe" (biasanya disimbolkan dengan T) yang menangkap tipe data saat fungsi dipanggil:
function dapatkanElemenPertama<T>(arr: T[]): T {return arr[0];}// Penggunaan:const nama = dapatkanElemenPertama(["Budi", "Siti", "Joko"]); // Tipe otomatis terdeteksi sebagai stringconst angka = dapatkanElemenPertama([10, 20, 30]); // Tipe otomatis terdeteksi sebagai number
Penggunaan Generics pada Interface
Generics juga sangat berguna pada interface. Contoh klasik adalah ketika membuat pembungkus respons API (API Response Wrapper):
interface ResponsAPI<TData> {status: 'sukses' | 'gagal';data: TData;pesan?: string;}// Penggunaan untuk data Penggunainterface Pengguna {id: string;nama: string;email: string;}const responsUser: ResponsAPI<Pengguna> = {status: 'sukses',data: {id: 'usr-101',nama: 'Budi Santoso',email: 'budi@gmail.com'}};
Dengan cara ini, kita tidak perlu membuat ResponsAPIPengguna, ResponsAPIProduk, dan sebagainya. Satu interface ResponsAPI bisa digunakan kembali untuk tipe data apa saja!
Batasan Generics (Generic Constraints)
Kadang kita ingin membatasi tipe data apa saja yang boleh diterima oleh Generics. Kita bisa menggunakan kata kunci extends untuk hal ini.
Misalnya, kita ingin membuat fungsi yang mencetak panjang properti .length dari argumennya. Kita harus memastikan bahwa argumen tersebut memiliki properti .length:
interface MemilikiPanjang {length: number;}function cetakPanjang<T extends MemilikiPanjang>(obj: T): void {console.log(`Panjangnya adalah: ${obj.length}`);}// Bekerja dengan string dan array karena keduanya punya properti .lengthcetakPanjang("Halo Dunia");cetakPanjang([1, 2, 3, 4]);// Error! Number tidak memiliki properti .length// cetakPanjang(123);
Kesimpulan
TypeScript Generics membantu Anda menulis kode yang bersih, modular, dan sangat reusable tanpa harus mengorbankan keamanan tipe data. Mulailah mengidentifikasi fungsi-fungsi di projek Anda yang mengulangi logika serupa dengan tipe yang berbeda, lalu ubahlah menjadi fungsi Generic!
Diskusi Pembaca (2)
Sangat bermanfaat kak, terima kasih banyak sharingnya!
Artikel yang sangat jelas! Penjelasan tentangextends sangat mudah dipahami.
