Interface Extends
Mewarisi dan menggabungkan interface dengan extends: DRY untuk tipe object.
Analogi: Resep Warisan Keluarga
Bayangin resep kue dasar keluarga: tepung, gula, telur. Anaknya bikin varian cokelat dengan menambah bubuk kakao, cucunya bikin varian keju dengan menambah parutan keju. Tidak ada yang nulis ulang resep dasar dari nol, semua "mewarisi" lalu menambahkan.
extends di interface bekerja persis seperti itu. Interface anak mewarisi semua properti interface induk, lalu boleh menambah properti sendiri.
Kenapa extends Ada?
Tanpa extends, hierarki tipe harus ditulis dengan copy-paste:
interface Pengguna {
id: string;
nama: string;
email: string;
}
interface Admin {
id: string; // salinan...
nama: string; // salinan...
email: string; // salinan...
levelAkses: number;
}Masalahnya klasik: besok Pengguna tambah properti avatar, kamu harus ingat mengupdate Admin, Pelanggan, Moderator, dan semua turunannya satu per satu. Satu saja kelupaan, kontrak datanya diam-diam tidak sinkron.
Dengan extends, hubungan ditulis sekali dan selalu sinkron:
interface Pengguna {
id: string;
nama: string;
email: string;
}
interface Admin extends Pengguna {
levelAkses: number;
}
const a: Admin = { id: "A1", nama: "Budi", email: "[email protected]", levelAkses: 3 };
// wajib punya semua properti Pengguna + levelAksesIni DRY (Don't Repeat Yourself) untuk tipe: satu sumber kebenaran untuk bentuk dasar.
Contoh Error Compiler yang Nyata
Warisan bukan berarti bebas. Properti yang dideklarasikan ulang harus kompatibel dengan induknya:
interface Hewan {
nama: string;
kaki: number;
}
interface Kucing extends Hewan {
kaki: string; // SALAH: induk bilang number
}
// Error: Interface 'Kucing' incorrectly extends interface 'Hewan'.
// Types of property 'kaki' are incompatible.
// Type 'string' is not assignable to type 'number'.Error ini sebenarnya penjaga yang baik: dia mencegah anak "mengkhianati" kontrak induknya. Kalau Hewan menjanjikan kaki berupa number, semua kode yang menerima Hewan berhak mengasumsikan itu.
Satu interface juga bisa extends banyak interface sekaligus:
interface Terbang { kecepatanTerbang: number; }
interface Berenang { kedalamanMaks: number; }
interface Bebek extends Terbang, Berenang {
nama: string;
}
const d: Bebek = { nama: "Donal", kecepatanTerbang: 40, kedalamanMaks: 5 };Kapan extends Berguna di Project Nyata
- Hierarki domain:
Penggunasebagai dasar, laluAdmin,Pelanggan,Kurirmenambah propertinya masing-masing. - API versioning: response v2 extends v1 lalu tambah field baru. Kode lama yang memakai v1 tetap aman.
- Props komponen:
ButtonProps extends BasePropsmenambahonClickdi atas properti dasar seperticlassNamedandisabled.
Catatan teknis:
extendshanya bisa dipakai olehinterface, dan hanya ke tipe berbentuk object. Untuktypealias, penggabungan dilakukan dengan intersection (&), dibahas di modul intersection-type. Perilakunya mirip, tapiextendsmemberi pesan error yang lebih jelas saat ada konflik properti.
Kesalahan Umum Pemula
1. Copy-paste properti induk alih-alih extends
SALAH:
interface Admin {
id: string; nama: string; email: string; // duplikat dari Pengguna
levelAkses: number;
}BENAR:
interface Admin extends Pengguna {
levelAkses: number;
}2. Mendeklarasikan ulang properti dengan tipe beda
SALAH:
interface Induk { kode: number; }
interface Anak extends Induk { kode: string; } // Error: incorrectly extendsBENAR:
interface Induk { kode: number; }
interface Anak extends Induk { kode: number; keterangan: string } // OK
// atau ubah tipenya di induk sekalian kalau memang salah di sana3. extends ke union type
SALAH:
type A_atau_B = { a: string } | { b: number };
interface C extends A_atau_B {}
// Error: An interface can only extend an object type or intersection of
// object types with statically known members.BENAR:
type C = A_atau_B & { c: boolean }; // intersection untuk type alias4. Lupa properti warisan saat bikin object
SALAH:
interface Kucing extends Hewan { sukaTidur: boolean; }
const k: Kucing = { sukaTidur: true };
// Error: Property 'nama' is missing... (warisan dari Hewan wajib diisi)BENAR:
const k: Kucing = { nama: "Mochi", sukaTidur: true };Tantangan
Hierarki kendaraan
Buat interface Kendaraan (merk: string, tahun: number), lalu Mobil extends Kendaraan tambah jumlahPintu: number, dan Motor extends Kendaraan tambah adaGigi: boolean. Buat satu object tiap tipe dan pastikan compiler menerima keduanya.
interface Kendaraan {
merk: string;
tahun: number;
}
// tulis Mobil dan Motor di sini
const avanza: Mobil = { merk: "Toyota", tahun: 2022, jumlahPintu: 4 };
const beat: Motor = { merk: "Honda", tahun: 2023, adaGigi: false };