Interface, extends & Intersection
Mendeskripsikan bentuk object dengan interface, mewarisi interface (extends), menggabungkan tipe dengan intersection (&), perbedaan interface vs type, dan declaration merging.
Interface: kontrak bentuk object
interface adalah cara lain (selain type) untuk memberi nama pada bentuk object. Ia seperti kontrak: siapa pun yang mengaku bertipe ini wajib memenuhi isinya.
interface Pengguna {
id: number
nama: string
email?: string // opsional
readonly dibuat: Date // tidak boleh diubah
sapa(): string // metode
}
const u: Pengguna = {
id: 1,
nama: "Ani",
dibuat: new Date(),
sapa() { return "Halo, " + this.nama },
}
Mewarisi dengan extends
Interface bisa memperluas interface lain, sehingga kamu tidak menyalin ulang properti:
interface Hewan {
nama: string
suara(): string
}
interface Anjing extends Hewan {
ras: string
}
// Interface boleh punya banyak induk sekaligus: interface C extends A, B { ... }
const bruno: Anjing = {
nama: "Bruno",
ras: "Golden",
suara: () => "Guk!",
}
Intersection (&): menggabungkan tipe
Operator & membuat tipe baru yang punya semua properti dari kedua sisi (kebalikan union yang "salah satu").
type Orang = { nama: string; umur: number }
type Gaji = { gaji: number }
type Pegawai = Orang & Gaji
const p: Pegawai = { nama: "Budi", umur: 30, gaji: 8000000 } // wajib lengkap semua
Pola yang sering muncul: menambahkan "bumbu" yang dipakai bersama.
type DenganWaktu = { dibuat: Date; diubah: Date }
type Artikel = { judul: string; isi: string } & DenganWaktu
type Komentar = { teks: string } & DenganWaktu
Interface vs type: pilih yang mana?
| Kemampuan | interface | type |
|---|---|---|
| Bentuk object | Ya | Ya |
| Mewarisi | extends | & (intersection) |
Union (A | B) | Tidak | Ya |
| Primitif, tuple, fungsi, literal | Terbatas | Ya |
| Declaration merging (digabung otomatis) | Ya | Tidak |
| Pesan error | Sedikit lebih jelas pada extends | Baik |
Pedoman praktis: pakai interface untuk bentuk object dan kontrak class (API publik), pakai type untuk union, tuple, fungsi, dan tipe turunan. Yang terpenting: konsisten dalam satu proyek.
Declaration merging
Dua interface dengan nama sama otomatis digabung. Fitur ini dipakai pustaka untuk memperluas tipe bawaan (misalnya menambah properti ke Window atau objek Request Express):
interface Pengaturan { tema: string }
interface Pengaturan { bahasa: string }
const s: Pengaturan = { tema: "gelap", bahasa: "id" } // harus memuat keduanya
Interface untuk fungsi dan index signature
interface Pembanding {
(a: number, b: number): number // call signature
}
interface Kamus {
[kata: string]: string // index signature
}
Struktural, bukan nominal
TypeScript memeriksa bentuk, bukan nama. Selama object punya properti yang dibutuhkan, ia dianggap cocok — disebut structural typing atau "duck typing":
interface Bernama { nama: string }
function salam(x: Bernama) { return "Hai " + x.nama }
const kucing = { nama: "Tom", warna: "abu" }
salam(kucing) // ✅ kucing punya nama, kelebihan properti tidak masalah (karena bukan literal langsung)
Kesalahan umum pemula
- Memberi awalan
Ipada nama interface (IUser) — gaya lama yang tidak lagi dianjurkan di TypeScript. - Mengira dua tipe dengan nama berbeda tidak kompatibel; yang dihitung adalah bentuknya.
- Mencampur interface dan type tanpa aturan sehingga proyek tidak konsisten.