K

Command Palette

Search for a command to run...

Daftar

Union & Intersection Types di TS

Bikin tipe datamu lebih fleksibel! Pelajari cara menggunakan Union Types untuk variabel yang bisa memiliki salah satu dari beberapa tipe, dan Intersection Types untuk menggabungkan beberapa tipe menjadi satu.

Tipe Jadi Fleksibel: Jurus Union (|) dan Intersection (&) di TypeScript!

Udah mulai jago kan ngasih tipe ke variabel, fungsi, dan objek pake TypeScript? Keren! Tapi, kadang kita butuh tipe yang lebih "luwes". Gimana kalau sebuah variabel itu bisa jadi string ATAU angka? Atau gimana kalau kita mau bikin tipe baru yang merupakan GABUNGAN dari dua tipe lain?

Nah, TypeScript punya dua "jurus kombinasi" tipe yang super berguna buat kasus kayak gini: Union Types (|) dan Intersection Types (&).

1. Union Types (|): "Bisa Ini ATAU Itu"

Union Type ngebolehin sebuah nilai buat jadi salah satu dari beberapa tipe yang udah ditentuin. Kita pake simbol pipe (|) buat misahin tipe-tipe yang mungkin.

  • Sintaks: TipeA | TipeB | TipeC
  • Artinya, variabel atau parameter yang punya tipe ini bisa diisi nilai yang tipenya TipeA, ATAU TipeB, ATAU TipeC.

Contoh Penggunaan Union Types:

typescript
// Variabel 'identitas' bisa string atau number
let identitas: string | number;
 
identitas = "user-007"; // Oke, string
console.log(identitas.toUpperCase()); // Aman, karena TS tau di sini 'identitas' itu string
 
identitas = 12345;      // Oke, number
console.log(identitas.toFixed(2)); // Aman, TS tau di sini 'identitas' itu number
 
// identitas = true; // ERROR! Boolean gak termasuk di union type string | number
 
// Fungsi yang bisa nerima string atau array string
function cetakPesan(pesan: string | string[]): void {
    if (typeof pesan === "string") {
        console.log("Pesan tunggal:", pesan);
    } else { // Di sini, TS tau 'pesan' pasti array string
        console.log("Daftar pesan:");
        pesan.forEach(p => console.log("- " + p));
    }
}
 
cetakPesan("Halo semua!");
cetakPesan(["Selamat pagi", "Apa kabar?", "Semoga sehat selalu"]);

Type Guards dengan Union Types: Pas kamu kerja sama variabel yang tipenya union, TypeScript cuma bakal ngizinin kamu pake properti atau metode yang ada di SEMUA tipe di dalem union itu (kalau ada). Kalau mau pake properti/metode yang spesifik buat salah satu tipe, kamu perlu "ngasih tau" TypeScript tipe apa sebenernya nilai itu saat itu. Ini namanya Type Guard.

Cara umum buat type guard:

  • Pake typeof buat ngecek tipe primitif (string, number, boolean, symbol, bigint, function).
  • Pake instanceof buat ngecek apakah sebuah objek itu instance dari class tertentu.
  • Pake operator in buat ngecek apakah properti tertentu ada di objek.
  • Bikin fungsi type guard kustom (lebih advance).

Contoh di fungsi cetakPesan di atas, kita pake typeof pesan === "string" sebagai type guard. Di dalem blok if itu, TypeScript jadi "yakin" kalau pesan itu string, jadi kita bisa pake metode string kayak toUpperCase() (meskipun gak dipake di contoh itu). Di blok else, TS tau pesan pasti string[].

Literal Types sebagai Bagian dari Union: Kamu juga bisa pake nilai literal (nilai spesifik) sebagai bagian dari union type. Ini berguna buat ngebatasin pilihan nilai yang boleh.

typescript
type Arah = "atas" | "bawah" | "kiri" | "kanan";
let gerakanPemain: Arah;
 
gerakanPemain = "atas";    // Oke
// gerakanPemain = "maju"; // ERROR! "maju" gak termasuk di tipe Arah
 
type UkuranTombol = "kecil" | "sedang" | "besar";
interface TombolProps {
    ukuran?: UkuranTombol; // Ukuran tombol cuma boleh salah satu dari itu
}

2. Intersection Types (&): "Harus Punya Sifat Ini DAN Itu"

Intersection Type dipake buat ngegabungin beberapa tipe jadi satu tipe baru yang punya SEMUA properti dan metode dari semua tipe yang digabungin itu. Kita pake simbol ampersand (&) buat misahin tipe-tipenya.

  • Sintaks: TipeA & TipeB & TipeC
  • Artinya, variabel atau objek yang punya tipe ini harus memenuhi "kontrak" dari TipeA DAN TipeB DAN TipeC sekaligus.

Contoh Penggunaan Intersection Types:

Bayangin kita punya dua interface yang beda: satu buat sesuatu yang bisa diseret (Draggable), satu lagi buat sesuatu yang ukurannya bisa diubah (Resizable). Terus kita mau bikin objek yang bisa diseret DAN ukurannya bisa diubah.

typescript
interface Draggable {
    drag: () => void; // Punya metode drag
}
 
interface Resizable {
    resize: (faktor: number) => void; // Punya metode resize
}
 
// Tipe WidgetInteraktif adalah gabungan dari Draggable DAN Resizable
type WidgetInteraktif = Draggable & Resizable;
 
let kotakAjaib: WidgetInteraktif = {
    // Harus punya properti/metode dari Draggable:
    drag: () => {
        console.log("Kotak lagi diseret...");
    },
    // DAN harus punya properti/metode dari Resizable:
    resize: (faktor) => {
        console.log(`Kotak diubah ukurannya jadi ${faktor}x`);
    }
    // Kalau salah satu gak ada, bakal error!
};
 
kotakAjaib.drag();
kotakAjaib.resize(1.5);
 
// Contoh lain: Gabungin tipe objek
type InfoDasar = {
    nama: string;
    umur: number;
};
 
type InfoKontak = {
    email: string;
    telepon?: string;
};
 
// PenggunaLengkap harus punya semua properti dari InfoDasar DAN InfoKontak
type PenggunaLengkap = InfoDasar & InfoKontak;
 
let penggunaBaru: PenggunaLengkap = {
    nama: "Dewi",
    umur: 22,
    email: "dewi@email.com",
    telepon: "08123" // telepon jadi wajib karena kita gabungin, bukan opsional lagi
                    // kecuali kalau InfoKontak punya telepon opsional dan kita mau
                    // PenggunaLengkap juga punya telepon opsional.
                    // Untuk itu, definisi PenggunaLengkap mungkin perlu disesuaikan jika
                    // perilaku opsional mau dipertahankan dari salah satu tipe.
};

Perhatian soal Intersection dengan Tipe Primitif: Kalau kamu coba gabungin tipe primitif yang gak mungkin ada barengan (misal, string & number), hasilnya bakal jadi tipe never (tipe yang gak mungkin punya nilai). Ini karena satu nilai gak bisa jadi string DAN angka sekaligus.

Kapan Pake Union vs. Intersection?

  • Pake Union Type (|) kalau:

    • Sebuah nilai bisa jadi salah satu dari beberapa kemungkinan tipe.
    • Kamu mau ngasih pilihan tipe yang terbatas buat parameter atau variabel.
  • Pake Intersection Type (&) kalau:

    • Kamu mau bikin tipe baru yang ngegabungin semua fitur atau properti dari beberapa tipe lain.
    • Kamu mau "mixin" atau "compose" beberapa bentuk objek jadi satu.

Union dan Intersection Types ini adalah alat yang sangat powerful di TypeScript buat bikin definisi tipe yang lebih fleksibel, modular, dan akurat sesuai kebutuhan datamu. Awalnya mungkin kerasa agak abstrak, tapi pas kamu mulai kerja sama data yang strukturnya beragam atau butuh ngombinasiin berbagai "sifat", dua jurus ini bakal sering kepake!

Ini ngebantu banget buat nulis kode yang lebih aman dan lebih gampang dipahami sama TypeScript (dan sama developernya juga!).

Kuis Union & Intersection Types di TypeScript

Pertanyaan 1 dari 5

Dalam TypeScript, apa yang dimaksud dengan Union Type yang ditulis menggunakan simbol `|` (misalnya, `string | number`)?