K

Command Palette

Search for a command to run...

Daftar

Objek, Interface, & Type Aliases TS

Berikan struktur pada datamu! Pelajari cara mendefinisikan bentuk objek di TypeScript menggunakan anotasi tipe inline, Interface, dan Type Aliases untuk kode yang lebih terorganisir dan type-safe.

Ngasih "Cetakan" ke Data: Objek, Interface, & Type Aliases di TypeScript!

Udah bisa ngasih tipe ke variabel dasar dan parameter fungsi? Keren! Sekarang, gimana kalau data kita itu lebih kompleks, misalnya data seorang pengguna yang punya nama, umur, email, dan alamat? Atau data produk yang punya ID, nama, harga, dan deskripsi?

Di JavaScript, kita biasa pake objek literal ({}) buat ngewakilin data terstruktur kayak gitu. Nah, di TypeScript, kita bisa (dan sangat disarankan buat) ngasih "cetakan" atau "bentuk" (shape) ke objek-objek ini biar lebih jelas properti apa aja yang seharusnya ada dan apa tipe datanya.

Ada beberapa cara buat ngedefinisiin bentuk objek di TypeScript:

  1. Anotasi Tipe Inline untuk Objek
  2. interface (Cara yang paling umum dan idiomatik buat objek)
  3. type Aliases (Lebih fleksibel, bisa buat tipe apa aja, termasuk objek)

Yuk, kita bedah satu-satu!

1. Anotasi Tipe Inline untuk Objek

Ini cara paling langsung buat ngasih tau tipe sebuah objek. Kamu definisiin bentuknya langsung pas deklarasi variabel atau parameter.

typescript
let pengguna: { 
    nama: string; 
    umur: number; 
    aktif: boolean; 
};
 
pengguna = {
    nama: "Budi Santoso",
    umur: 30,
    aktif: true
};
 
// pengguna = { nama: "Siti", umur: "dua puluh" }; // ERROR! Umur harus number
// pengguna = { nama: "Ani" }; // ERROR! Properti 'umur' dan 'aktif' hilang
 
function cetakInfoProduk(produk: { id: number; nama: string; harga?: number }) { // harga opsional
    console.log(`Produk: ${produk.nama} (ID: ${produk.id})`);
    if (produk.harga) {
        console.log(`Harga: Rp ${produk.harga}`);
    }
}
 
cetakInfoProduk({ id: 101, nama: "Laptop Keren", harga: 15000000 });
cetakInfoProduk({ id: 102, nama: "Mouse Gaming" }); // Oke, harga opsional

Cara ini oke buat objek simpel yang cuma dipake sekali atau dua kali. Tapi, kalau bentuk objek yang sama mau kamu pake di banyak tempat, nulis ulang anotasinya terus-terusan jadi gak efisien. Nah, di situlah interface dan type aliases masuk.

2. interface: Bikin "Kontrak Bentuk" Objek yang Reusable!

interface di TypeScript adalah cara yang powerful buat ngasih nama ke sebuah struktur objek. Dia kayak "kontrak" atau "blueprint" yang ngasih tau properti apa aja yang harus (atau boleh) ada di objek, beserta tipe datanya.

  • Sintaks Dasar interface:
    typescript
    interface NamaInterfaceKamu {
        namaProperti1: TipeData1;
        namaProperti2: TipeData2;
        propertiOpsional?: TipeData3; // Tanda tanya (?) buat properti opsional
        readonly propertiReadOnly: TipeData4; // Cuma bisa dibaca, gak bisa diubah setelah inisialisasi objek
        metodeLagi?(param: Tipe): TipeReturn; // Metode juga bisa didefinisikan
    }

Contoh Penggunaan interface:

typescript
interface Pengguna {
    id: number;
    nama: string;
    email: string;
    alamat?: string; // Alamat itu opsional
    readonly tanggalDaftar: Date; // Gak bisa diubah setelah diset
    sapa(): string; // Metode yang harus ada dan mengembalikan string
}
 
let pengguna1: Pengguna = {
    id: 1,
    nama: "Citra Lestari",
    email: "citra@email.com",
    tanggalDaftar: new Date(),
    sapa: function() { // atau sapa() { return `Halo, ${this.nama}`; }
        return `Halo, nama saya ${this.nama}`;
    }
};
 
// pengguna1.tanggalDaftar = new Date(); // ERROR! tanggalDaftar itu readonly
// pengguna1.id = 2; // ERROR jika id didefinisikan sbg readonly interface Pengguna { readonly id: number; ... }
 
console.log(pengguna1.sapa()); // Output: Halo, nama saya Citra Lestari
 
let pengguna2: Pengguna = {
    id: 2,
    nama: "Andi Wijaya",
    email: "andi@email.com",
    alamat: "Jl. Mawar No. 10", // Ngasih nilai ke properti opsional
    tanggalDaftar: new Date(),
    sapa: () => `Hi, I'm Andi` // Implementasi metode bisa beda
};

Kelebihan interface:

  • Reusable: Kamu bisa pake nama interface (Pengguna) di banyak tempat sebagai tipe.
  • Jelas dan Deskriptif: Langsung keliatan "bentuk" data yang diharapkan.
  • Bisa di-extend (Declaration Merging & Inheritance):
    • Kamu bisa nambahin properti baru ke interface yang udah ada dengan ngedeklarasiin interface dengan nama yang sama lagi (Declaration Merging).
    • Satu interface bisa "mewarisi" properti dari interface lain pake keyword extends.
    typescript
    interface Karyawan extends Pengguna { // Karyawan mewarisi semua properti Pengguna
        jabatan: string;
        gaji: number;
    }
     
    let karyawan1: Karyawan = {
        id: 3,
        nama: "Dewi Anggraini",
        email: "dewi@email.com",
        tanggalDaftar: new Date(),
        sapa: () => `Hello, ${karyawan1.nama}`,
        jabatan: "Software Engineer",
        gaji: 20000000
    };

3. type Aliases: Ngasih Nama ke Tipe Apa Aja (Termasuk Bentuk Objek)

type Aliases ngasih kita cara buat ngasih nama alias ke tipe apa pun. Ini bisa tipe primitif, union type, intersection type, tuple, function type, dan pastinya bentuk objek juga.

  • Sintaks Dasar type Alias buat Objek:
    typescript
    type NamaTypeAliasKamu = {
        namaProperti1: TipeData1;
        namaProperti2: TipeData2;
        // ... mirip kayak daleman interface
    };

Contoh Penggunaan type Alias buat Objek:

typescript
type TitikKoordinat = {
    x: number;
    y: number;
    label?: string;
};
 
let titikA: TitikKoordinat = { x: 10, y: 20 };
let titikB: TitikKoordinat = { x: 5, y: 15, label: "Titik B" };
 
// Type alias juga bisa buat tipe lain:
type ID = string | number; // Union type
type FungsiCallback = (data: any) => void; // Function type
 
let idPengguna: ID = "user-123";
idPengguna = 456; // Oke
 
const prosesData: FungsiCallback = (hasil) => {
    console.log("Data diproses:", hasil);
};

interface vs. type Aliases buat Objek: Kapan Pake yang Mana?

Buat ngedefinisiin "bentuk" objek, interface dan type aliases itu seringkali bisa dipake secara bergantian dan punya banyak kemiripan. Tapi, ada beberapa perbedaan kunci dan konvensi:

  • Declaration Merging: interface mendukung declaration merging, type aliases enggak. Artinya, kalau kamu definisiin dua interface dengan nama yang sama, TypeScript bakal ngegabungin propertinya. Ini kadang berguna buat nge-extend interface dari library pihak ketiga.

    typescript
    interface Mobil { merek: string; }
    interface Mobil { tahun: number; } // Ini bakal digabung jadi Mobil { merek: string; tahun: number; }
     
    // type DataMobil = { merek: string; };
    // type DataMobil = { tahun: number; }; // ERROR! Gak bisa redeclare type alias DataMobil.
  • Extending/Implementing:

    • interface bisa extends interface lain (atau class). Class juga bisa implements interface (buat mastiin class itu punya properti/metode tertentu).
    • type aliases bisa ngelakuin hal mirip inheritance pake intersection types (&).
      typescript
      type KendaraanDasar = { roda: number; };
      type MobilTipe = KendaraanDasar & { pintu: number; merek: string; }; // Pake intersection
  • Fleksibilitas type: type aliases lebih fleksibel karena dia bisa ngasih nama ke tipe apa pun, gak cuma bentuk objek (misal, union type, tuple, tipe primitif). interface itu khusus buat ngedefinisiin bentuk objek (atau class).

Saran Umum dari Komunitas (Gak Aturan Baku):

  • Pake interface kalau kamu lagi ngedefinisiin "bentuk" dari sebuah objek atau "kontrak" buat sebuah class. Karena lebih jelas tujuannya buat objek dan dukung declaration merging.
  • Pake type alias kalau kamu mau ngasih nama ke union type, intersection type, tuple, atau tipe fungsi, atau kalau kamu butuh fitur yang cuma ada di type (kayak mapped types, conditional types - ini udah advance).

Tapi, buat kasus objek simpel, dua-duanya seringkali bisa dipake. Yang penting konsisten di proyekmu.

Properti Opsional (?) dan Read-only (readonly)

Kita udah singgung sedikit di atas, tapi ini penting:

  • Properti Opsional (?): Tambahin tanda tanya ? setelah nama properti dan sebelum titik dua tipe datanya di interface atau type objek. Ini artinya properti itu gak wajib ada pas objeknya dibikin. Kalau diakses dan gak ada, nilainya undefined.

    typescript
    interface Produk {
        nama: string;
        harga: number;
        deskripsi?: string; // deskripsi ini opsional
    }
    let buku: Produk = { nama: "Buku TypeScript", harga: 150000 }; // Oke, deskripsi gak ada
  • Properti Read-only (readonly): Tambahin keyword readonly sebelum nama properti. Ini artinya nilai properti itu cuma bisa diset pas objeknya pertama kali dibikin. Setelah itu, gak bisa diubah lagi nilainya.

    typescript
    interface User {
        readonly id: number;
        username: string;
    }
    let userBaru: User = { id: 1, username: "budi_ts" };
    // userBaru.id = 2; // ERROR! Properti 'id' itu readonly.
    userBaru.username = "budi_keren"; // Oke, username bisa diubah.

    readonly ini bagus buat properti yang emang seharusnya gak pernah berubah, kayak ID unik.


Dengan interface dan type aliases, kamu bisa bikin "cetakan" yang jelas buat struktur data objekmu. Ini bikin kode TypeScript-mu jadi lebih aman, gampang dipahami, dan enak banget buat di-maintain, apalagi pas datanya makin kompleks atau kamu kerja bareng tim.

Biasain diri buat ngedefinisiin bentuk datamu pake interface atau type sebelum kamu mulai ngolah data itu. Ini investasi kecil di awal yang bakal ngasih banyak manfaat di belakang!

Kuis Objek, Interface, & Type Aliases di TypeScript

Pertanyaan 1 dari 4

Manakah cara yang PALING umum dan direkomendasikan di TypeScript untuk mendefinisikan 'bentuk' atau struktur sebuah objek yang akan digunakan ulang di banyak tempat?