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:
- Anotasi Tipe Inline untuk Objek
interface
(Cara yang paling umum dan idiomatik buat objek)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.
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
:
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:
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 duainterface
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
bisaextends
interface lain (atau class). Class juga bisaimplements
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 ditype
(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 diinterface
atautype
objek. Ini artinya properti itu gak wajib ada pas objeknya dibikin. Kalau diakses dan gak ada, nilainyaundefined
.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 keywordreadonly
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?