Stop Kopi Paste Interface yang Sama, Coba Deh Bikin Type Utility di TypeScript

Stop Kopi Paste Interface yang Sama, Coba Deh Bikin Type Utility di TypeScript
Photo by Patrick Martin/Unsplash

Bayangkan ini: Kamu sedang mengerjakan proyek aplikasi atau website, entah itu dashboard admin, e-commerce, atau sistem manajemen internal. Kamu punya interface buat data user, sebut saja UserProfile. Di sana ada id, name, email, dan address. Lalu, tiba-tiba kamu butuh interface baru untuk proses update profil, tapi kamu tahu, saat update, semua properti itu opsional, dan kamu juga tidak boleh mengubah id. Apa yang biasanya kamu lakukan?

Kalau jawabanmu adalah, “Ya udah, gue copy-paste aja interface yang tadi, terus tambahin tanda tanya (?) di setiap properti selain id,” well, selamat datang di neraka copy-paste yang sering dihadapi banyak developer.

Metode kuno seperti itu mungkin cepat di awal, tapi percaya deh, itu adalah resep pasti untuk technical debt yang menumpuk. Ketika aplikasi makin besar, kamu akan punya puluhan interface yang 90% isinya sama. Kalau ada perubahan di struktur data utama (misalnya, name dipecah jadi firstName dan lastName), kamu harus ubah di semua tempat. Capek, boros waktu, dan rentan bug.

Di Javapixa Creative Studio, kami selalu menekankan bahwa efisiensi bukan hanya soal kecepatan loading aplikasi, tapi juga soal kecepatan dan kebersihan kode yang kami tulis. Itulah kenapa kita perlu ngobrol serius soal Type Utility di TypeScript.

Type Utility adalah ‘perkakas sakti’ yang disediakan oleh TypeScript untuk memanipulasi, mengubah, atau mengambil tipe data yang sudah ada tanpa perlu mendefinisikan ulang dari nol. Intinya, ini adalah cara paling elegan untuk menerapkan prinsip DRY (Don't Repeat Yourself) di level typing.

Kenapa Type Utility Harus Jadi Menu Wajib Harianmu?

Kalau kamu ingin aplikasi atau website yang kamu kembangkan stabil, mudah di-maintain, dan siap skala besar—seperti yang kami bangun di Javapixa Creative Studio—kamu harus menggunakan Type Utility.

  1. Mengurangi Boilerplate: Kamu bisa membuat tipe yang kompleks hanya dengan menggabungkan tipe-tipe dasar.
  2. Konsistensi: Memastikan bahwa semua tipe turunan selalu mengikuti perubahan dari tipe induknya.
  3. Refactoring Jadi Gampang: Kalau ada perubahan di tipe data utama, perubahannya akan otomatis terpropagasi ke tipe turunan yang dibuat menggunakan Type Utility.

Mari kita bongkar satu per satu Type Utility yang paling sering dipakai dan bagaimana cara memaksimalkannya agar codebase-mu bersih dari virus copy-paste.

---

The Big Five: Type Utility yang Wajib Kamu Kuasai

Ini adalah lima Type Utility standar yang harusnya sudah kamu gunakan di setiap proyek TypeScript. Anggap ini adalah palu, obeng, dan kunci pas di toolbox pengembangan aplikasi modern.

1. Partial: Segala Sesuatunya Jadi Opsional

Inilah solusi untuk masalah update profil yang kita bahas di awal. Partial mengambil semua properti dari tipe T dan membuatnya menjadi opsional (menambahkan tanda ?).

typescript
interface User {
  id: number;
  username: string;
  email: string;
  isActive: boolean;
}// PartialUser = { id?: number; username?: string; email?: string; isActive?: boolean; }
type PartialUser = Partial;

Dengan satu baris kode Partial, kamu sudah menyelamatkan diri dari mengetik ulang empat properti dengan tanda tanya. Praktis, bukan?

2. Required: Memaksa Properti Jadi Wajib

Ini kebalikan dari Partial. Jika kamu punya interface di mana sebagian properti sudah diatur sebagai opsional, tapi di kasus tertentu kamu membutuhkan semua properti itu hadir, Required adalah jawabannya.

typescript
interface Settings {
  theme?: 'dark' | 'light';
  notifications?: boolean;
}

Ini sangat berguna saat kamu ingin memastikan sebuah objek sudah melalui validasi dan semua nilainya sudah terisi sebelum dikirim ke backend.

3. Readonly: Anti-Perubahan Dadakan

Bayangkan kamu mengambil data dari API yang bersifat statis (misalnya, daftar kategori). Kamu tidak ingin ada kode di aplikasi (yang mungkin di-handle developer lain) yang secara tidak sengaja mengubah data itu.

typescript
interface Product {
  sku: string;
  price: number;
}

Ketika kamu mendeklarasikan sebuah variabel bertipe ReadonlyProduct, kamu dijamin tidak akan bisa menugaskan nilai baru ke properti di dalamnya. Ini adalah pengaman yang sangat penting untuk data yang sensitif atau bersifat cache.

4. Pick: Ambil yang Kamu Mau Aja

Seringkali, kamu hanya butuh subset kecil dari sebuah interface yang besar. Daripada membuat interface baru yang isinya sama persis, gunakan Pick.

Pick memungkinkan kamu memilih properti (K) dari tipe yang sudah ada (T).

typescript
interface FullCustomer {
  id: number;
  name: string;
  phone: string;
  address: string;
  orderHistory: string[];
}

Ini sangat membantu ketika kamu mendefinisikan tipe untuk props komponen React yang hanya membutuhkan dua atau tiga data dari objek utuh.

5. Omit: Buang yang Tidak Perlu

Ini adalah kembaran dari Pick, tapi kerjanya terbalik. Omit mengambil tipe T dan menghapus properti yang kamu sebutkan di K.

Kembali ke kasus update profil, biasanya kita tidak boleh mengirimkan id saat update karena id itu immutable (tidak bisa diubah).

typescript
interface User {
  id: number;
  username: string;
  email: string;
}// UserUpdatePayload = { username: string; email: string; }
type UserUpdatePayload = Omit;

Lihat? Dengan menggabungkan Omit dan Partial, kamu mendapatkan tipe yang presisi dan maintainable hanya dalam satu baris, tanpa perlu copy-paste sama sekali. Di Javapixa Creative Studio, kombinasi seperti ini adalah praktik standar untuk memastikan setiap payload API terdefinisi dengan jelas.

---

Senjata Rahasia: Type Utility Tingkat Lanjut

Setelah kamu nyaman dengan Big Five, saatnya kita naik kelas. Type Utility ini mungkin tidak dipakai setiap hari, tapi saat kamu membutuhkannya, mereka adalah penyelamat sejati, terutama ketika berurusan dengan union types atau fungsi.

6. Exclude dan Extract (Berurusan dengan Union Type)

Union Type ('admin' | 'user' | 'guest') adalah hal yang sangat umum di TypeScript.

  • Exclude: Berguna untuk menghilangkan tipe tertentu (U) dari sebuah Union Type (T).
typescript
    type Roles = 'admin' | 'editor' | 'viewer';
    // PublicRoles = 'editor' | 'viewer' (admin di-exclude)
    type PublicRoles = Exclude;

Extract: Kebalikannya, hanya menyimpan tipe yang ada di kedua Union (T dan U). Ini berguna untuk memastikan sebuah tipe adalah subset* dari tipe lain.

7. NonNullable: Membasmi null dan undefined

Kalau kamu berurusan dengan data yang mungkin mengandung null atau undefined (misalnya data yang baru di-fetch), tapi kamu tahu di titik tertentu dalam kode datanya sudah pasti ada, kamu bisa menggunakan ini untuk membersihkan tipenya.

typescript
type MaybeString = string | null | undefined;

Ini membantu compiler mengerti bahwa kamu tidak perlu lagi melakukan pengecekan if (data) yang berulang-ulang, membuat kode lebih ringkas.

8. ReturnType dan Parameters (Introspeksi Fungsi)

Ini adalah utility yang sangat kuat ketika kamu bekerja dengan fungsi. Mereka memungkinkan kamu mengambil informasi tentang tipe input dan output sebuah fungsi tanpa memanggil fungsinya.

ReturnType: Mengambil tipe data yang akan dikembalikan oleh fungsi T. Ini sangat berguna untuk mendefinisikan tipe data state di React berdasarkan hasil sebuah fungsi fetch* data. Parameters: Mengambil tipe data dari argumen-argumen fungsi T dalam bentuk tuple*.

typescript
function calculatePrice(amount: number, discount: number): number {
  return amount - discount;
}// ReturnValue = number
type ReturnValue = ReturnType;

Bayangkan betapa rapihnya kode kamu: tipe untuk state atau variabelmu otomatis ter-update hanya dengan mengubah definisi fungsi utamanya. Ini adalah esensi dari kode yang self-maintaining.

Membangun Toolset Kustom Sendiri

Kekuatan sejati Type Utility bukan hanya menggunakan yang sudah ada, tapi juga menggabungkannya untuk menciptakan utility kustom yang sangat spesifik untuk kebutuhan proyekmu.

Contoh sederhana, kamu ingin membuat semua properti opsional, kecuali properti id.

typescript
// Custom Utility: Jadikan Tipe Opsional, Kecuali Properti K
type OptionalExceptFor =
  Partial & Pick;interface DataItem {
  id: number;
  name: string;
  description: string;
}

Ini adalah contoh type manipulation yang canggih. Dengan definisi UpdateItemPayload di atas, kamu wajib menyertakan id, tetapi sisanya bebas opsional. Ini adalah level kejelasan tipe yang kami terapkan di Javapixa Creative Studio untuk memastikan developer dan API kami selalu sinkron tanpa bug yang tidak perlu.

Penutup: Standar Kualitas Javapixa Creative Studio

Menggunakan Type Utility bukan sekadar trik keren dalam koding. Ini adalah fondasi dari codebase yang profesional dan siap untuk berkembang.

Bayangkan jika kamu membangun aplikasi skala besar. Tanpa Type Utility, developer akan menghabiskan waktu berjam-jam hanya untuk memastikan tipe data antar komponen match, atau lebih parah, mereka akan membuat kesalahan typing yang baru ketahuan saat runtime.

Di Javapixa Creative Studio, ketika kami menawarkan jasa pembuatan website dan aplikasi yang kompleks—mulai dari sistem ERP kustom hingga platform digital berskala tinggi—kami menjamin kode yang robust. Salah satu pilar utama dari jaminan itu adalah kepatuhan ketat terhadap praktik TypeScript terbaik, termasuk penggunaan Type Utility yang cerdas dan efisien.

Kami melihat Type Utility sebagai investasi. Investasi waktu sebentar di awal untuk mendefinisikan tipe yang fleksibel akan menghemat ratusan jam debugging dan refactoring di masa depan.

Jadi, buat kamu yang masih suka kopi paste interface, stop mulai hari ini. Sisihkan waktu sebentar, pelajari Omit, Pick, dan kombinasi lainnya. Codebase kamu akan berterima kasih, dan kamu akan mulai merasakan bagaimana rasanya ngoding dengan tingkat efisiensi ala developer profesional di creative studio terdepan. Mari bersama-sama menuju era typing yang lebih cerdas dan minim error!