Catatan lanjutan dari kelas be10x kemarin
Daftar Isi
- Apa Itu Utility Types?
- Partial<T>
- Required<T>
- Readonly<T>
- Pick<T, K>
- Omit<T, K>
- Record<K, T>
- Exclude<T, U>
- Extract<T, U>
- NonNullable<T>
- InstanceType<T>
- Contoh Kasus Dunia Nyata
- Praktik Terbaik dalam Menggunakan Utility Types
- Kesimpulan
Apa Itu Utility Types?
Utility Types adalah tipe-tipe bawaan di TypeScript yang memudahkan manipulasi tipe yang sudah ada untuk membuat tipe baru. Mereka membantu dalam pengembangan dengan membuat tipe lebih dinamis dan fleksibel tanpa mengorbankan keamanan tipe.
Mengapa Menggunakan Utility Types?
- Efisiensi: Mengurangi jumlah kode yang perlu ditulis.
- Reusability: Memungkinkan penggunaan kembali tipe yang sudah ada dengan modifikasi.
- Keamanan Tipe: Memastikan konsistensi dan keamanan tipe dalam aplikasi.
Pendapat Pribadi: Dalam pengalaman saya, Utility Types sangat membantu dalam mengelola tipe data yang kompleks, terutama dalam aplikasi skala besar.
Partial<T>
Partial<T>
membuat semua properti dalam tipe T
menjadi opsional.
Ilustrasi Partial<T>
Loading graph...
graph TD A[Type T] B["Partial<T>"] A -->|Semua properti wajib| A B -->|Semua properti opsional| Bgraph TD A[Type T] B["Partial<T>"] A -->|Semua properti wajib| A B -->|Semua properti opsional| B
Penjelasan Ilustrasi:
- Type T: Memiliki semua properti yang wajib diisi.
- Partial
: Mengubah semua properti dalamT
menjadi opsional.
Contoh 1: Menggunakan Partial<T>
interface User {
id: number;
name: string;
email: string;
}
function updateUser(user: User, updates: Partial<User>): User {
return { ...user, ...updates };
}
let user1: User = { id: 1, name: "Ibrahim", email: "[email protected]" };
let updatedUser = updateUser(user1, { email: "[email protected]" });
console.log(updatedUser);
// Output: { id: 1, name: "Ibrahim", email: "[email protected]" }
Penjelasan:
Partial<User>
memungkinkan kita untuk hanya memberikan sebagian dari propertiUser
.- Sangat berguna dalam fungsi update atau patch.
Required<T>
Required<T>
membuat semua properti dalam tipe T
menjadi wajib (non-opsional).
Ilustrasi Required<T>
Loading graph...
graph TD A[Type T dengan properti opsional] B["Required<T>"] A -->|Beberapa properti opsional| B B -->|Semua properti wajib| Agraph TD A[Type T dengan properti opsional] B["Required<T>"] A -->|Beberapa properti opsional| B B -->|Semua properti wajib| A
Penjelasan Ilustrasi:
- Type T dengan properti opsional: Beberapa properti mungkin opsional.
- Required
: Mengubah semua properti menjadi wajib.
Contoh 2: Menggunakan Required<T>
interface User {
id: number;
name?: string;
email?: string;
}
let user2: Required<User> = {
id: 2,
name: "Ali",
email: "[email protected]",
};
// Akan error jika properti name atau email tidak ada.
Pendapat Pribadi: Required<T>
berguna ketika kita ingin memastikan bahwa semua properti harus ada, misalnya saat menyimpan data ke database.
Readonly<T>
Readonly<T>
membuat semua properti dalam tipe T
menjadi hanya-baca.
Ilustrasi Readonly<T>
Loading graph...
graph LR T[Type T: User] T -- properti dapat diubah --> "Readonly<T>" "Readonly<T>" -- properti menjadi hanya-baca --> Tgraph LR T[Type T: User] T -- properti dapat diubah --> "Readonly<T>" "Readonly<T>" -- properti menjadi hanya-baca --> T
Penjelasan Ilustrasi:
- Type T dengan properti dapat diubah: Properti dalam
T
dapat dimodifikasi. - Readonly
: Membuat semua properti menjadi hanya-baca.
Contoh 3: Menggunakan Readonly<T>
interface User {
id: number;
name: string;
}
let user3: Readonly<User> = {
id: 3,
name: "Fatimah",
};
// user3.name = "Aisyah"; // Error: Cannot assign to 'name' because it is a read-only property.
Catatan: Menggunakan Readonly<T>
membantu mencegah perubahan yang tidak diinginkan pada objek, meningkatkan integritas data.
Pick<T, K>
Pick<T, K>
membuat tipe baru dengan memilih subset properti K
dari tipe T
.
Ilustrasi Pick<T, K>
Loading graph...
graph LR T[Type T: User] K["Properties K: 'id', 'name'"] T -- pilih properti K --> "Pick<T, K>" "Pick<T, K>" -- hanya properti K --> Tgraph LR T[Type T: User] K["Properties K: 'id', 'name'"] T -- pilih properti K --> "Pick<T, K>" "Pick<T, K>" -- hanya properti K --> T
Penjelasan Ilustrasi:
- Type T dengan semua properti: Memiliki sejumlah properti.
- Pick<T, K>: Membuat tipe baru hanya dengan properti yang dipilih
K
.
Contoh 4: Menggunakan Pick<T, K>
interface User {
id: number;
name: string;
email: string;
age: number;
}
type UserPreview = Pick<User, "id" | "name">;
let userPreview: UserPreview = {
id: 4,
name: "Zainab",
};
Penjelasan:
UserPreview
hanya memiliki propertiid
danname
.
Omit<T, K>
Omit<T, K>
membuat tipe baru dengan menghilangkan properti K
dari tipe T
.
Ilustrasi Omit<T, K>
Loading graph...
graph LR T[Type T: User] K["Properties K: 'password'"] T -- semua properti --> "Omit<T, K>" "Omit<T, K>" -- tanpa properti K --> Tgraph LR T[Type T: User] K["Properties K: 'password'"] T -- semua properti --> "Omit<T, K>" "Omit<T, K>" -- tanpa properti K --> T
Penjelasan Ilustrasi:
- Type T dengan semua properti: Memiliki sejumlah properti.
- Omit<T, K>: Membuat tipe baru dengan menghilangkan properti tertentu
K
.
Contoh 5: Menggunakan Omit<T, K>
type UserWithoutEmail = Omit<User, "email">;
let userWithoutEmail: UserWithoutEmail = {
id: 5,
name: "Umar",
age: 28,
};
Penjelasan:
UserWithoutEmail
memiliki semua propertiUser
kecualiemail
.
Record<K, T>
Record<K, T>
membuat tipe objek dengan kunci tipe K
dan nilai tipe T
.
Ilustrasi Record<K, T>
Loading graph...
graph LR subgraph K [Keys K] A["admin"] B["user"] C["guest"] end T[Type T: Permissions] K -- menjadi kunci --> "Record<K, T>" T -- menjadi nilai --> "Record<K, T>"graph LR subgraph K [Keys K] A["admin"] B["user"] C["guest"] end T[Type T: Permissions] K -- menjadi kunci --> "Record<K, T>" T -- menjadi nilai --> "Record<K, T>"
Penjelasan Ilustrasi:
- Keys K: Sekumpulan kunci yang akan digunakan.
- Type T: Tipe nilai untuk setiap kunci.
- Record<K, T>: Objek baru dengan kunci
K
dan nilaiT
.
Contoh 6: Menggunakan Record<K, T>
type Roles = "admin" | "user" | "guest";
interface Permissions {
canRead: boolean;
canWrite: boolean;
canDelete: boolean;
}
let rolePermissions: Record<Roles, Permissions> = {
admin: { canRead: true, canWrite: true, canDelete: true },
user: { canRead: true, canWrite: true, canDelete: false },
guest: { canRead: true, canWrite: false, canDelete: false },
};
Pendapat Pribadi: Record<K, T>
sangat berguna untuk membuat objek map dengan tipe kunci dan nilai yang spesifik.
Exclude<T, U>
Exclude<T, U>
membuat tipe dengan mengecualikan tipe U
dari tipe T
.
Ilustrasi Exclude<T, U>
Loading graph...
graph LR subgraph T [Set T] A["active"] B["inactive"] C["pending"] end subgraph U [Set U] A["active"] end subgraph "Exclude<T, U>" B["inactive"] C["pending"] end T -- dikurangi U --> "Exclude<T, U>"graph LR subgraph T [Set T] A["active"] B["inactive"] C["pending"] end subgraph U [Set U] A["active"] end subgraph "Exclude<T, U>" B["inactive"] C["pending"] end T -- dikurangi U --> "Exclude<T, U>"
Penjelasan Ilustrasi:
- Set T: Sekumpulan tipe awal.
- Set U: Tipe yang akan dikecualikan.
- Exclude<T, U>: Tipe baru tanpa elemen dari
U
.
Contoh 7: Menggunakan Exclude<T, U>
type Status = "active" | "inactive" | "pending";
type ActiveStatus = Exclude<Status, "inactive">;
// ActiveStatus hanya "active" atau "pending"
Extract<T, U>
Extract<T, U>
membuat tipe dengan mengekstrak tipe yang ada di T
dan U
.
Ilustrasi Extract<T, U>
Loading graph...
graph TD A[Set T] B[Set U] C["Extract<T, U>"] A -->|Semua elemen T| A B -->|Elemen yang akan diekstrak| B A -.->|Mengambil elemen yang sama dengan U| Cgraph TD A[Set T] B[Set U] C["Extract<T, U>"] A -->|Semua elemen T| A B -->|Elemen yang akan diekstrak| B A -.->|Mengambil elemen yang sama dengan U| C
Penjelasan Ilustrasi:
- Set T: Sekumpulan tipe awal.
- Set U: Tipe yang akan diekstrak.
- Extract<T, U>: Tipe baru dengan elemen yang ada di
T
danU
.
Contoh 8: Menggunakan Extract<T, U>
type Status = "active" | "inactive" | "pending";
type VisibleStatus = Extract<Status, "active" | "pending">;
// VisibleStatus adalah "active" atau "pending"
NonNullable<T>
NonNullable<T>
membuat tipe dengan menghilangkan null
dan undefined
dari tipe T
.
Ilustrasi NonNullable<T>
Loading graph...
graph TD A[Type T dengan null dan undefined] B["NonNullable<T>"] A -->|Menghilangkan null dan undefined| Bgraph TD A[Type T dengan null dan undefined] B["NonNullable<T>"] A -->|Menghilangkan null dan undefined| B
Penjelasan Ilustrasi:
- Type T dengan null dan undefined: Tipe yang mungkin mengandung
null
atauundefined
. - NonNullable
: Tipe baru tanpanull
danundefined
.
Contoh 9: Menggunakan NonNullable<T>
type Name = string | null | undefined;
type ValidName = NonNullable<Name>;
// ValidName hanya string, tidak termasuk null atau undefined
Catatan: Sangat berguna ketika kita ingin memastikan bahwa tipe tidak mengandung null
atau undefined
.
InstanceType<T>
InstanceType<T>
mendapatkan tipe instance dari constructor atau class.
Ilustrasi InstanceType<T>
Loading graph...
graph TD A[Constructor T] B["InstanceType<T>"] A -->|Mendapatkan tipe instance dari T| Bgraph TD A[Constructor T] B["InstanceType<T>"] A -->|Mendapatkan tipe instance dari T| B
Penjelasan Ilustrasi:
- Constructor T: Sebuah kelas atau constructor function.
- InstanceType
: Tipe dari instance yang dihasilkan olehT
.
Contoh 10: Menggunakan InstanceType<T>
class Person {
constructor(public name: string, public age: number) {}
}
type PersonInstance = InstanceType<typeof Person>;
let person: PersonInstance = new Person("Aisha", 25);
Contoh Kasus Dunia Nyata
Membuat Formulir Dinamis
Dalam pengembangan aplikasi web, kita sering perlu membuat formulir yang dinamis. Utility Types dapat membantu dalam kasus ini.
interface FormFields {
username: string;
password: string;
rememberMe?: boolean;
}
type FormFieldsOptional = Partial<FormFields>;
function createForm(fields: FormFieldsOptional) {
// Logika untuk membuat formulir
}
createForm({ username: "user123" });
Penjelasan:
- Menggunakan
Partial<FormFields>
memungkinkan kita membuat formulir dengan sebagian field saja.
Mengelola Response API
Ketika bekerja dengan API, kita mungkin mendapatkan data yang sebagian besar tidak kita butuhkan.
interface ApiResponse {
id: number;
name: string;
email: string;
password: string; // Tidak perlu di frontend
}
type SafeApiResponse = Omit<ApiResponse, "password">;
function handleResponse(response: SafeApiResponse) {
// Logika untuk menangani response tanpa password
}
Pendapat Pribadi: Utility Types membantu menjaga keamanan dengan menghilangkan data sensitif seperti password dari tipe yang digunakan di frontend.
Praktik Terbaik dalam Menggunakan Utility Types
-
Pahami Kebutuhan Anda
Pilih Utility Type yang sesuai dengan kebutuhan spesifik Anda.
-
Gunakan untuk Mengurangi Duplikasi Kode
Manfaatkan Utility Types untuk menghindari penulisan ulang tipe yang mirip.
-
Perhatikan Keamanan Tipe
Pastikan penggunaan Utility Types tidak mengorbankan keamanan tipe dalam aplikasi.
-
Dokumentasikan Kode Anda
Jelaskan penggunaan Utility Types dalam kode untuk membantu tim memahami tujuan Anda.
-
Kombinasikan dengan Type Assertion Jika Perlu
Dalam beberapa kasus, Anda mungkin perlu menggunakan Type Assertion bersama dengan Utility Types.
Catatan: Utility Types adalah alat yang kuat, tetapi seperti semua alat, harus digunakan dengan bijak. Jangan gunakan secara berlebihan yang dapat membuat kode menjadi sulit dipahami.
Kesimpulan
Utility Types di TypeScript menawarkan cara yang efisien dan aman untuk memanipulasi tipe data. Dengan memahami dan menggunakan Utility Types seperti Partial
, Required
, Readonly
, Pick
, Omit
, Record
, dan lainnya, Anda dapat menulis kode yang lebih fleksibel dan mudah dipelihara.
Rekomendasi Selanjutnya:
Baca juga Artikel tentang Generic di Typescript
Pendapat Pribadi: Dalam perjalananku belajar TypeScript kembali, Utility Types telah menjadi salah satu fitur favorit saya. Mereka membantuku menulis kode yang lebih efisien dan terstruktur, terutama dalam proyek-proyek small ke mid.
Semoga artikel ini memberikan wawasan yang berguna bagi Anda. Jika Anda memiliki pertanyaan atau ingin berdiskusi lebih lanjut, jangan ragu untuk menghubungi saya. Selamat ngoding dan teruslah berinovasi!
Semoga catatan ini bermanfaat bagi saya pribadi dan teman-teman semua. Mari kita terus belajar dan berbagi ilmu untuk kemajuan bersama.