interfaceobjecttipe-dataPemula3 mnt baca

Interface Dasar

Mendefinisikan kontrak bentuk object dengan interface: cara paling idiomatis di TypeScript.

Analogi: Formulir Pendaftaran

Bayangin kamu panitia lomba. Setiap peserta ngisi formulir yang sama: nama, umur, nomor HP. Formulir itu "cetakannya", data tiap peserta adalah "isiannya". Kalau ada yang ngisi umur pakai tulisan "tujuh belas" atau lupa ngisi nama, panitia langsung protes.

interface di TypeScript itu formulirnya. Dia mendefinisikan bentuk (shape) sebuah object: properti apa saja yang wajib ada dan tipenya apa. Compiler jadi "panitia" yang ngecek setiap object sebelum program jalan.

Kenapa Interface Ada?

Di JavaScript murni, bentuk object cuma "kesepakatan lisan". Kamu bikin object user di satu file dengan properti nama, di file lain ngetiknya name karena lupa, dan bug-nya baru ketahuan pas aplikasi crash di tangan user.

Masalah yang diselesaikan interface:

  1. Anotasi object yang diulang-ulang. Tanpa interface, setiap fungsi yang menerima user harus nulis { nama: string; umur: number } berulang kali. Sekali bentuknya berubah, kamu harus ubah di semua tempat.
  2. Typo properti yang lolos diam-diam. Salah ketik emial bukannya email tidak akan ketahuan sampai runtime.
  3. Dokumentasi bentuk data. Interface adalah dokumentasi yang bisa dieksekusi: bentuk data API, props komponen, dan config semuanya terdokumentasi dalam kode.

Contoh masalahnya dulu:

typescript
// Tanpa interface: anotasi diulang di mana-mana
function simpanUser(u: { nama: string; umur: number }) { /* ... */ }
function tampilkanUser(u: { nama: string; umur: number }) { /* ... */ }
// Besok tambah properti email -> ubah dua-duanya. Lelah.

Versi rapi dengan interface:

typescript
interface Pengguna {
  nama: string;
  umur: number;
}

function simpanUser(u: Pengguna) { /* ... */ }
function tampilkanUser(u: Pengguna) { /* ... */ }
// Tambah email? Cukup ubah interface-nya sekali.

Contoh Error Compiler yang Nyata

Compiler tidak main-main soal kontrak. Lihat:

typescript
interface Siswa {
  nama: string;
  umur: number;
}

const a: Siswa = { nama: "Budi", umur: 17 }; // OK
const b: Siswa = { nama: "Ani" };
// Error: Property 'umur' is missing in type '{ nama: string; }'
//        but required in type 'Siswa'.

const c: Siswa = { nama: "Cici", umur: "tujuh belas" };
// Error: Type 'string' is not assignable to type 'number'.

Pesan errornya selalu menunjuk properti yang bermasalah dan tipe yang diharapkan. Ini jauh lebih murah daripada debugging di runtime.

Properti Opsional dan Readonly

Tidak semua properti wajib. Tanda ? artinya boleh tidak ada, readonly artinya tidak boleh diubah setelah dibuat:

typescript
interface Produk {
  readonly id: string;
  nama: string;
  diskon?: number; // boleh tidak ada
}

const p: Produk = { id: "P-1", nama: "Kopi" }; // OK, diskon absen
p.id = "P-2";
// Error: Cannot assign to 'id' because it is a read-only property.

Kombinasi ini sangat umum untuk data dari API: id tidak boleh diubah siapa pun, diskon kadang tidak dikirim server.

Catatan teknis: readonly hanya dijaga saat compile time. Kalau object-nya datang dari JSON.parse, tidak ada yang mencegah kode nakal mengubahnya lewat any. Anggap readonly sebagai rambu, bukan gembok.

Kesalahan Umum Pemula

1. Menyalin anotasi object ke mana-mana

SALAH:

typescript
function a(u: { nama: string; umur: number }) {}
function b(u: { nama: string; umur: number }) {}
function c(u: { nama: string; umur: number }) {}
// Tambah satu properti = ubah tiga tempat

BENAR:

typescript
interface Pengguna { nama: string; umur: number; }
function a(u: Pengguna) {}
function b(u: Pengguna) {}
function c(u: Pengguna) {}
// Tambah properti = ubah satu tempat

2. Lupa tanda ? lalu protes saat properti absen

SALAH:

typescript
interface Produk { nama: string; diskon: number; }
const p: Produk = { nama: "Kopi" };
// Error: Property 'diskon' is missing...
// Padahal diskon memang boleh tidak ada

BENAR:

typescript
interface Produk { nama: string; diskon?: number; }
const p: Produk = { nama: "Kopi" }; // OK

3. Pakai prefix I seperti di C#

SALAH:

typescript
interface ISiswa { nama: string; } // gaya C#, tidak idiomatis di TS

BENAR:

typescript
interface Siswa { nama: string; } // PascalCase polos

4. Mengira readonly melindungi saat runtime

SALAH (ekspektasi keliru):

typescript
interface Config { readonly apiKey: string; }
const cfg = JSON.parse('{"apiKey":"abc"}') as Config;
(cfg as any).apiKey = "diubah"; // lolos! readonly cuma compile-time

BENAR (pahami batasnya):

typescript
// readonly mencegah salah tulis di kode sendiri, bukan serangan.
// Untuk data sensitif, jangan taruh di client sama sekali.

Kapan Dipakai di Project Nyata

Hampir di semua tempat: bentuk response API (interface UserResponse), props komponen React (interface ButtonProps), baris data di tabel, dan object konfigurasi. Aturan praktisnya: kalau sebuah bentuk object dipakai lebih dari sekali atau diekspor ke file lain, beri dia interface. Kalau cuma sekali pakai di satu fungsi kecil, anotasi inline masih boleh.

Tantangan

Kontrak data pengguna

Buat interface Pengguna dengan id: string (readonly), nama: string, email: string, dan umur?: number. Lalu buat dua object: satu valid, satu yang sengaja salah (umur diisi string). Amati error compilernya.

typescript
interface Pengguna {
  // tulis di sini
}

const valid: Pengguna = { id: "U1", nama: "Budi", email: "[email protected]" };
const salah: Pengguna = { id: "U2", nama: "Ani", email: "[email protected]", umur: "tujuh belas" };