Langsung ke konten
KamusNgoding
Pemula Typescript 3 menit baca

Interface dan Type Alias di TypeScript

#typescript #interface #type-alias #optional #readonly #intersection #extends
📚

Baca dulu sebelum ini:

Saat aplikasi tumbuh besar, kamu akan banyak bekerja dengan objek yang memiliki struktur tertentu — data pengguna, produk, respons API. TypeScript menyediakan dua cara untuk mendefinisikan “kontrak” struktur objek: interface dan type alias. Keduanya adalah fondasi untuk menulis kode TypeScript yang terorganisir dan reusable. Di artikel ini kita akan mempelajari keduanya secara mendalam beserta kapan menggunakan masing-masing.

Mendefinisikan Struktur Objek Tanpa Interface

// Cara inline — susah di-reuse
function tampilkan_pengguna(user: { nama: string; umur: number; email: string }): void {
    console.log(`${user.nama} (${user.umur}) — ${user.email}`);
}

// Jika ada 10 fungsi yang butuh struktur yang sama, kamu harus tulis ulang semua

Interface dan type alias menyelesaikan masalah ini.

Interface

interface Pengguna {
    id: number;
    nama: string;
    email: string;
    umur: number;
}

// Sekarang bisa digunakan di banyak tempat
function tampilkan(user: Pengguna): void {
    console.log(`[${user.id}] ${user.nama} — ${user.email}`);
}

function kirim_email(user: Pengguna, pesan: string): void {
    console.log(`Kirim ke ${user.email}: "${pesan}"`);
}

const ali: Pengguna = {
    id: 1,
    nama: "Ali Akbar",
    email: "ali@email.com",
    umur: 25
};

tampilkan(ali);
// Output: [1] Ali Akbar — ali@email.com

// Struktur tidak lengkap → error
const tidak_lengkap: Pengguna = { id: 2, nama: "Budi" };
// ❌ Error: Property 'email' is missing

Optional Properties

interface Profil {
    username: string;
    nama_lengkap: string;
    bio?: string;          // Optional: boleh tidak ada
    website?: string;      // Optional
    avatar_url?: string;   // Optional
}

// Valid — field wajib saja
const profil_minimal: Profil = {
    username: "ali_akbar",
    nama_lengkap: "Ali Akbar"
};

// Valid — dengan beberapa optional
const profil_lengkap: Profil = {
    username: "budi_santoso",
    nama_lengkap: "Budi Santoso",
    bio: "Backend developer di Jakarta",
    website: "https://budi.dev"
};

// Cara aman mengakses optional property
function cetak_bio(profil: Profil): void {
    console.log(`@${profil.username}: ${profil.bio ?? "Belum ada bio"}`);
}

cetak_bio(profil_minimal);
// Output: @ali_akbar: Belum ada bio
cetak_bio(profil_lengkap);
// Output: @budi_santoso: Backend developer di Jakarta

Readonly Properties

interface KonfigurasiApp {
    readonly nama_app: string;     // Tidak bisa diubah setelah inisialisasi
    readonly versi: string;
    tema: "gelap" | "terang";      // Bisa diubah
    bahasa: string;
}

const config: KonfigurasiApp = {
    nama_app: "KamusNgoding",
    versi: "2.0.0",
    tema: "gelap",
    bahasa: "id"
};

config.tema = "terang";     // ✅ Valid — bisa diubah
config.bahasa = "en";       // ✅ Valid
config.nama_app = "Lain";   // ❌ Error: Cannot assign to 'nama_app' (readonly)

Extending Interface

Interface bisa diwariskan — cara yang bersih untuk membangun hierarki tipe:

interface EntitasDasar {
    id: number;
    dibuat_pada: Date;
    diperbarui_pada: Date;
}

interface Produk extends EntitasDasar {
    nama: string;
    harga: number;
    kategori: string;
}

interface ProdukDigital extends Produk {
    url_unduh: string;
    ukuran_mb: number;
}

const ebook: ProdukDigital = {
    id: 1,
    dibuat_pada: new Date("2026-01-01"),
    diperbarui_pada: new Date("2026-04-01"),
    nama: "Belajar TypeScript",
    harga: 99_000,
    kategori: "Buku",
    url_unduh: "https://cdn.kamusngoding.com/ebook.pdf",
    ukuran_mb: 12.5
};

console.log(`${ebook.nama} — Rp ${ebook.harga.toLocaleString("id-ID")}`);
// Output: Belajar TypeScript — Rp 99.000

Multiple Interface Inheritance

interface Timestampable {
    dibuat_pada: Date;
    diperbarui_pada: Date;
}

interface Softdeletable {
    dihapus_pada?: Date;
    is_dihapus: boolean;
}

// Implements keduanya sekaligus
interface Artikel extends Timestampable, Softdeletable {
    judul: string;
    konten: string;
}

Type Alias

Type alias memberi nama pada tipe yang sudah ada — lebih fleksibel dari interface:

// Alias untuk tipe primitif
type ID = number;
type NamaLengkap = string;

// Alias untuk union type — sangat berguna!
type StatusPesanan = "menunggu" | "diproses" | "dikirim" | "selesai" | "dibatalkan";
type Tema = "gelap" | "terang" | "sistem";
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";

function ubah_status(pesanan_id: ID, status: StatusPesanan): void {
    console.log(`Pesanan ${pesanan_id} → ${status}`);
}

ubah_status(42, "dikirim");    // ✅ Valid
ubah_status(42, "hilang");     // ❌ Error: tidak ada dalam union type

// Alias untuk objek — mirip interface
type Koordinat = {
    lat: number;
    lng: number;
    label?: string;
};

const jakarta: Koordinat = { lat: -6.2088, lng: 106.8456, label: "Jakarta" };

Intersection Type — Menggabungkan Type

type PengggunaDasar = {
    id: number;
    nama: string;
};

type InfoAkun = {
    email: string;
    password_hash: string;
};

type PenggunaLengkap = PengggunaDasar & InfoAkun; // Gabungan semua field

const user: PenggunaLengkap = {
    id: 1,
    nama: "Ali",
    email: "ali@email.com",
    password_hash: "abc123xyz"
};

Interface vs Type Alias — Kapan Menggunakan Mana?

// Interface: lebih baik untuk mendefinisikan "kontrak" objek/class
// Bisa di-extend dan di-implement oleh class
interface HewanPeliharaan {
    nama: string;
    suara(): string;
}

class Kucing implements HewanPeliharaan {
    nama: string;
    constructor(nama: string) { this.nama = nama; }
    suara() { return "Meow!"; }
}

// Type alias: lebih fleksibel — bisa union, intersection, primitif
type HewanAtauNull = HewanPeliharaan | null;
type ID = string | number; // ← Interface tidak bisa untuk ini
InterfaceType Alias
Objek/shape
Class implements
Extends (inheritance)Lewat intersection &
Union type
Primitif alias
Declaration merging✅ (bisa re-deklarasi)

Panduan praktis: Gunakan interface untuk mendefinisikan struktur objek dan kontrak class. Gunakan type untuk union type, literal type, dan alias primitif.

Pertanyaan yang Sering Diajukan

Apakah interface dan type alias bisa digunakan bergantian?

Untuk mendefinisikan bentuk objek, ya — interface Pengguna { ... } dan type Pengguna = { ... } hampir identik. Perbedaan utama: interface mendukung declaration merging (kamu bisa deklarasikan interface yang sama dua kali dan TypeScript menggabungkannya), berguna untuk memperluas tipe dari library eksternal. Type alias tidak mendukung ini.

Apa itu declaration merging pada interface?

Jika kamu mendeklarasikan interface dengan nama yang sama dua kali, TypeScript otomatis menggabungkannya. Contoh: interface Window { myCustomProp: string } akan menambahkan myCustomProp ke interface Window bawaan browser. Ini berguna saat kamu perlu menambahkan properti ke tipe dari library eksternal tanpa mengubah source-nya.

Apakah readonly di TypeScript benar-benar immutable?

readonly di TypeScript hanya mencegah re-assignment pada level type checking — ini compile-time only. Saat runtime (JavaScript), nilai masih bisa diubah dengan cara tertentu. Jika kamu butuh immutability sejati di runtime, gunakan Object.freeze() atau library seperti Immer.

Bagaimana cara mendefinisikan array of objects dengan interface?

interface Item { id: number; nama: string }
const items: Item[] = [{ id: 1, nama: "A" }, { id: 2, nama: "B" }];

Atau gunakan Array<Item> sebagai alternatif.

Kesimpulan

KonsepSintaksKeterangan
Interface dasarinterface Nama { ... }Kontrak struktur objek
Optional propertyprop?: typeBoleh tidak ada
Readonly propertyreadonly prop: typeTidak bisa diubah
Extendsinterface B extends AMewarisi interface
Type aliastype Nama = ...Nama untuk tipe apapun
UnionA | BSalah satu tipe
IntersectionA & BGabungan semua property

Artikel sebelumnya: Fungsi dengan Tipe di TypeScript — cara mengetik fungsi.

Langkah selanjutnya: Generics dan Class di TypeScript — cara membuat kode yang reusable dengan generics dan class yang type-safe.

Artikel Terkait