Episode ini membuka generik, alat paling kuat untuk menulis ulang kode yang berlaku untuk banyak tipe. Kalian akan belajar fungsi generik, type parameter, konstrain dengan extends, serta interface dan class generik dengan type parameter default.

Bayangkan menulis fungsi identik yang menangani array string, array number, dan array objek. Tanpa bantuan, kalian menyalin kode tiga kali atau membuang jaminan tipe dengan any. Generik menyelesaikan keduanya sekaligus: satu implementasi, tipe yang tetap dipertahankan.
Generik adalah cara menulis tipe yang parametrik, yaitu tipe yang menerima argumen tipe. Analoginya seperti fungsi pada nilai: fungsi nilai menerima argumen nilai dan mengembalikan nilai, sedangkan generik menerima argumen tipe dan menghasilkan tipe konkret.
Episode 8 membahas fungsi generik, konstrain agar type parameter tidak liar, generik pada interface dan class, serta type parameter default. Ini fondasi untuk membaca dan menulis library TypeScript yang sesungguhnya.
Fungsi generik dideklarasikan dengan type parameter dalam kurung sudut:
function elemenPertama<T>(data: T[]): T | undefined {
return data[0];
}
const angka = elemenPertama([10, 20, 30]);
const kata = elemenPertama(["a", "b"]);Deklarasi function elemenPertama<T>(data: T[]): T menyatakan bahwa tipe kembalian sama dengan tipe elemen array yang masuk. Saat dipanggil dengan array number, hasilnya number. TypeScript menyimpulkan T secara otomatis, jadi tidak perlu menulis tipe di sisi pemanggilan.
Contoh paling klasik adalah fungsi identitas:
function identitas<T>(nilai: T): T {
return nilai;
}
const teks = identitas("halo");
const nomor = identitas(42);Fungsi identitas menerima nilai apa pun dan mengembalikannya dengan tipe yang sama. Tanpa generik, fungsi ini harus bertipe any dan kehilangan semua informasi tipe. Dengan generik, setiap pemanggilan mendapat tipe yang tepat.
Type parameter yang tidak dibatasi bisa menerima apa saja. Konstrain membatasi ke bentuk tertentu:
interface PunyaPanjang {
length: number;
}
function ukuran<T extends PunyaPanjang>(input: T): number {
return input.length;
}
ukuran("halo");
ukuran([1, 2, 3]);
ukuran(123);Konstrain T extends PunyaPanjang menjamin input punya properti length, sehingga akses input.length aman. Pemanggilan dengan number akan ditolak compiler karena number tidak punya length. Konstrain menjaga tubuh fungsi tetap valid untuk semua tipe yang diizinkan.
Generik tidak hanya untuk fungsi. Interface dan class juga bisa parametrik:
interface Kotak<T> {
isi: T;
}
class Penyimpan<T> {
private nilai: T;
constructor(nilai: T) {
this.nilai = nilai;
}
ambil(): T {
return this.nilai;
}
}
const kunci = new Penyimpan<string>("rahasia");
const kataKunci: string = kunci.ambil();interface Kotak<T> mendefinisikan kontrak yang isinya bertipe T. class Penyimpan<T> menahan nilai bertipe T dan mengembalikannya bertipe T. Instance Penyimpan<string> hanya bisa menyimpan dan mengembalikan string, dicek sepenuhnya oleh compiler.
Type parameter bisa punya nilai bawaan seperti parameter fungsi:
interface Respons<T = string> {
sukses: boolean;
data: T;
}
const teksRespons: Respons = { sukses: true, data: "ok" };
const angkaRespons: Respons<number> = { sukses: true, data: 200 };interface Respons<T = string> memakai string bila pemanggil tidak menyebutkan tipe. Pemanggilan dengan Respons<number> tetap dimungkinkan. Default membuat tipe generik mudah dipakai untuk kasus umum tanpa mengorbankan fleksibilitas kasus khusus.
Info
Konvensi penamaan type parameter: pakai satu huruf besar seperti T, K, atau V untuk kasus sederhana, dan nama deskriptif seperti Data atau Error untuk generik yang maknanya penting. Nama yang jelas membantu pembaca memahami hubungan antar tipe.
Episode 8 memberi kalian senjata terkuat sistem tipe TypeScript: generik. Dengan fungsi, konstrain, interface, class, dan type parameter default, kalian bisa menulis satu implementasi yang aman untuk banyak tipe tanpa menyalin kode atau jatuh ke any.
Inti yang harus dibawa pulang:
extends membatasi type parameter agar punya bentuk tertentu.Di episode 9 selanjutnya kita akan membahas class, inheritance, modifiers, dan abstraksi, yaitu cara membangun objek dengan perilaku bersama dan mengatur akses anggota di bawah sistem tipe.