Utility type adalah generic type bawaan TypeScript yang mengubah satu tipe menjadi tipe lain. Alih-alih menulis tipe User kedua dengan semua field opsional, kamu menulis Partial<User>; alih-alih menyalin tiga field, Pick<User, "id" | "name">. Utility type bersifat global, jadi tidak perlu import.
Ketika User berubah, keempat tipe turunannya ikut berubah. Standard library TypeScript (lib.es5.d.ts) mendeklarasikan 22 utility type. Bagian-bagian di bawah ini mendaftar semuanya, dikelompokkan berdasarkan jenis tipe yang diolahnya, dengan link ke halaman detailnya kalau ada.
Object Type: Partial, Required, Readonly, Pick, Omit, Record
| Utility type | Fungsinya | Contoh |
|---|---|---|
Partial<T> | membuat setiap property menjadi opsional | Partial<User> untuk payload update |
Required<T> | membuat setiap property menjadi wajib (menghapus ?) | Required<Config> setelah nilai default diterapkan |
Readonly<T> | membuat setiap property menjadi readonly | Readonly<State> |
Pick<T, K> | hanya mempertahankan key K | Pick<User, "id" | "name"> |
Omit<T, K> | menghapus key K | Omit<User, "password"> |
Record<K, V> | object type dengan key K dan nilai V | Record<"en" | "de", string> |
Required<T> adalah kebalikan dari Partial<T>; halaman Partial membahas keduanya, termasuk undefined eksplisit yang bisa lolos lewat spread seperti ini.
Union Type: Exclude, Extract, NonNullable
| Utility type | Fungsinya | Contoh |
|---|---|---|
Exclude<U, M> | membuang anggota union yang bisa diberikan ke M | Exclude<"a" | "b" | "c", "a"> adalah "b" | "c" |
Extract<U, M> | mempertahankan anggota union yang bisa diberikan ke M | Extract<string | number, number> adalah number |
NonNullable<T> | membuang null dan undefined | NonNullable<string | null> adalah string |
Ketiganya bekerja pada union, bukan object. Itulah perbedaan utamanya dengan Pick dan Omit, yang menerima object type dan daftar key-nya.
Tipe Fungsi dan Class: Parameters, ReturnType, dan Lainnya
| Utility type | Fungsinya | Contoh |
|---|---|---|
ReturnType<F> | tipe kembalian dari sebuah tipe fungsi | ReturnType<typeof createStore> |
Parameters<F> | tipe-tipe parameter sebagai tuple | Parameters<typeof fetchPage>[0] |
ConstructorParameters<C> | parameter constructor sebuah class sebagai tuple | ConstructorParameters<typeof Point> |
InstanceType<C> | tipe instance yang dibuat sebuah constructor | InstanceType<typeof Point> |
ThisParameterType<F> | tipe parameter this sebuah fungsi | ThisParameterType<typeof greet> |
OmitThisParameter<F> | tipe fungsi tanpa parameter this-nya | tipe dari greet.bind(obj) |
ThisType<T> | menetapkan tipe this di dalam method sebuah object literal | dipakai dengan noImplicitThis di API builder |
NoInfer<T> | mencegah type parameter disimpulkan dari posisi ini | fallback: NoInfer<C> |
typeof createOrder diperlukan karena utility ini menerima tipe, sedangkan createOrder adalah nilai. Hal yang sama berlaku untuk class: typeof Point adalah tipe constructor, sedangkan Point biasa sebagai tipe sudah berarti tipe instance.
NoInfer mengatur dari mana sebuah generic mendapat tipenya:
Tanpa NoInfer, TypeScript akan menyimpulkan C dari kedua argumen dan melebarkannya menjadi "red" | "green" | "blue", sehingga salah ketik di nilai fallback akan diterima.
Tipe String: Uppercase, Lowercase, Capitalize, Uncapitalize
| Utility type | Fungsinya | Contoh |
|---|---|---|
Uppercase<S> | mengubah tipe string literal menjadi huruf besar | Uppercase<"get"> adalah "GET" |
Lowercase<S> | mengubahnya menjadi huruf kecil | Lowercase<"GET"> adalah "get" |
Capitalize<S> | mengubah karakter pertama menjadi huruf besar | Capitalize<"name"> adalah "Name" |
Uncapitalize<S> | mengubah karakter pertama menjadi huruf kecil | Uncapitalize<"Name"> adalah "name" |
Keempatnya dibangun langsung di dalam compiler, bukan ditulis dengan TypeScript, dan paling berguna di dalam template literal types, seperti `on${Capitalize<E>}` untuk nama event handler.
Promise: Awaited
| Utility type | Fungsinya | Contoh |
|---|---|---|
Awaited<T> | tipe yang kamu dapat dari await, membuka promise bersarang | Awaited<Promise<Promise<number>>> adalah number |
Awaited<ReturnType<typeof fn>> adalah cara standar untuk menamai tipe hasil sebuah fungsi async tanpa mendeklarasikannya secara terpisah.
Menggabungkan Utility Type
Utility type bisa disusun bersarang. Beberapa kombinasi cukup sering muncul sehingga layak dihafal:
Baca utility type bersarang dari dalam ke luar: Readonly<Pick<Post, "id" | "title">> pertama-tama mempertahankan dua property, lalu membuatnya read-only. Bagian-bagian yang sama membentuk helper PartialBy yang hanya membuat sebagian key menjadi opsional; halaman Partial menuliskannya secara lengkap.
Utility Type Tidak Melakukan Apa Pun Saat Runtime
Setiap utility type dihapus ketika kode dikompilasi. Nilai bertipe Omit<User, "password"> tetap bisa membawa password saat runtime kalau object asalnya punya password:
Tipe hanya membatasi apa yang boleh dibaca oleh kodemu. Untuk menghapus sebuah field dari data, buang field itu dengan destructuring seperti di baris-baris terakhir, dan untuk mencegah perubahan saat runtime, pakai Object.freeze, bukan Readonly. Tipe bawaan ini adalah mapped type dan conditional type satu baris, jadi alat yang sama memungkinkanmu menulis utility type sendiri.
Pertanyaan yang sering diajukan
Apa itu utility type di TypeScript?
Generic type yang sudah tersedia di TypeScript dan mengubah tipe lain: Partial<T> membuat setiap property menjadi opsional, Pick<T, K> mempertahankan sebagian property, ReturnType<F> mengambil tipe kembalian sebuah fungsi, dan seterusnya. Semuanya dideklarasikan di standard library, jadi kamu memakainya tanpa meng-import apa pun.
Apakah utility type perlu di-import?
Tidak. Partial, Omit, Record, ReturnType dan lainnya adalah tipe global dari file library bawaan TypeScript. Tulis Partial<User> di mana saja; tidak perlu import dan tidak perlu package npm.
Utility type apa saja yang sudah ada di TypeScript?
Ada 22, semuanya dideklarasikan di lib.es5.d.ts: Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, Parameters, ConstructorParameters, ReturnType, InstanceType, ThisParameterType, OmitThisParameter, ThisType, NoInfer, Awaited, Uppercase, Lowercase, Capitalize dan Uncapitalize.
Apakah utility type mengubah object saat runtime?
Tidak. Utility type hanya menjelaskan tipe dan dihapus dari output JavaScript. Omit<User, "password"> tidak menghapus property password, dan Readonly<T> tidak membekukan apa pun. Untuk mengubah object yang sebenarnya, tulis kodenya: pola rest pada destructuring, Object.freeze, dan sebagainya.
Bisakah membuat utility type sendiri?
Bisa. Utility type bawaan adalah TypeScript biasa: sebagian besar berupa mapped type atau conditional type satu baris di lib.es5.d.ts. type Nullable<T> = { [K in keyof T]: T[K] | null } adalah utility type buatan sendiri yang ditulis dengan cara yang sama.