Tipe Berguna TypeScript — Yang Perlu Dihafal (dan yang Lainnya)
Sebagian, Pilih, Sisakan, Catat, ReturnType, Parameter, Awaited — delapan tipe utilitas dengan contoh sebelum dan sesudah serta penilaian jujur mengenai tipe-tipe mana yang akan Anda gunakan setiap minggu.
Anda mungkin sudah membaca halaman dokumentasi TypeScript yang menyebutkan lebih dari 20 tipe utilitas dalam urutan alfabetis, mendefinisikan setiap tipe dalam satu kalimat, dan membuat Anda bertanya-tanya mana yang seharusnya dikuasai secara internal dan mana yang hanya digunakan oleh orang yang menulis bagian internal kerangka kerja. Ini adalah versi yang lebih jujur: delapan tipe, contoh sebelum dan sesudah yang konkret, serta jawaban langsung mengenai penggunaan harian dibandingkan penggunaan yang jarang terjadi.
Jika Anda mulai dari JSON murni dan belum menulis antarmuka Anda, maka pembuat konversi JSON ke TypeScript akan membawa Anda ke antarmuka dasar dalam beberapa detik — lalu kembali ke sini untuk menambahkan tipe utilitas ini.
Partial — Penggunaan mingguan. Pelajari terlebih dahulu.
Membuat setiap properti di T opsional. Kasus penggunaan klasik adalah pembaruan berbentuk PATCH, di mana Anda hanya mengirimkan bidang-bidang yang berubah.
// Before: manually duplicating the interface with optional versions of everything
interface UserUpdate {
name?: string;
email?: string;
age?: number;
}
// After: Partial derives it from the source of truth
interface User {
name: string;
email: string;
age: number;
}
function updateUser(id: string, updates: Partial<User>) {
// updates.name is string | undefined — TypeScript knows
}
Masalah pada versi "sebelumnya": jika Anda menambahkan sebuah properti ke User, Anda harus mengingat untuk menambahkannya ke UserUpdate pula. Dengan Partial<User>, menambahkan sebuah properti ke antarmuka sumber secara otomatis membuatnya tersedia dalam pembaruan. Tipe-tipe tetap sinkron.
Required — Penggunaan bulanan, tetapi menghemat Anda dalam satu skenario tertentu.
Kebalikan dari Partial — menghapus semua ? dari suatu tipe. Paling berguna setelah validasi: Anda menerima objek konfigurasi yang tidak terstruktur, memverifikasi bahwa semua bidang ada, dan kemudian ingin TypeScript berhenti menyarankan bahwa semua nilai mungkin tidak terisi.
// Before: after validating, you still fight undefined checks everywhere
interface Config {
apiUrl?: string;
timeout?: number;
retries?: number;
}
function initApp(config: Config) {
config.apiUrl?.trim(); // need optional chaining even after checking
}
// After: Required signals "this has been validated, stop warning me"
function validateAndInit(raw: Config): void {
if (!raw.apiUrl) throw new Error("apiUrl required");
if (!raw.timeout) throw new Error("timeout required");
if (!raw.retries) throw new Error("retries required");
const config = raw as Required<Config>;
config.apiUrl.trim(); // no optional chaining needed
}
Catatan yang jujur: Required<T> tidak melakukan validasi di runtime — Anda tetap harus menulis pengecekan tersebut. Ini hanya mengubah apa yang diyakini TypeScript di level tipe. Gunakan ini untuk menyampaikan “ini telah divalidasi” pada tingkat tipe.
Pick — Penggunaan mingguan. Pilih apa yang Anda inginkan.
Membuat tipe baru yang hanya mengandung properti yang Anda sebutkan dari T. Berguna ketika Anda ingin subset dari antarmuka yang lebih besar — bentuk API publik, model tampilan, respons terstruktur.
// Before: manually maintaining a separate interface that drifts from User
interface UserPublicProfile {
name: string;
bio: string;
avatarUrl: string;
}
// After: Pick stays in sync with the source
interface User {
id: string;
name: string;
email: string; // private — shouldn't go to clients
passwordHash: string; // definitely private
bio: string;
avatarUrl: string;
}
type UserPublicProfile = Pick<User, "name" | "bio" | "avatarUrl">;
Pick adalah alat yang tepat ketika daftar properti yang Anda inginkan lebih pendek daripada daftar yang Anda butuhkan untuk exclude. Ketika arahnya terbalik, gunakan Omit.
Omit — Penggunaan mingguan. Pilih apa yang tidak Anda inginkan.
Kompresi dari Pick — membuat tipe yang memiliki semua properti dari T kecuali yang Anda sebutkan. Ketika Anda memiliki antarmuka besar dan hanya beberapa bidang yang perlu dihapus, Omit membuat niat lebih jelas daripada menyebutkan semua yang Anda inginkan.
// Before: manually listing every field except the sensitive ones
// Easy to miss a new field added to User later
interface UserForClient {
id: string;
name: string;
email: string;
bio: string;
avatarUrl: string;
// passwordHash intentionally omitted — but a future dev might not know that
}
// After: Omit states the exclusion explicitly
type UserForClient = Omit<User, "passwordHash">;
// If User gains a new "address" field, UserForClient gets it automatically
Satu hal yang tidak dilakukan oleh Pick atau Omit: mengubah tipe properti individu. Jika Anda ingin memilih bidang-bidang dan dan mengubah tipe mereka, Anda sedang mencari tipe pemetaan, yang merupakan alat yang berbeda secara utuh.
Record — Penggunaan mingguan. Dikatakan sebagai kamus terstruktur.
Membuat tipe objek di mana semua kunci berjenis K dan semua nilai berjenis V. Manfaat nyata muncul ketika K adalah tipe gabungan — TypeScript akan memberi kesalahan jika Anda melewatkan kunci. Tanda indeks umum secara diam-diam menerima objek yang tidak lengkap; Record dengan kunci gabungan tidak.
// Before: index signature with no exhaustiveness checking
const rolePermissions: { [key: string]: string[] } = {
admin: ["read", "write", "delete"],
editor: ["read", "write"],
// forgot "viewer" — TypeScript doesn't notice
};
// After: Record with a union key enforces completeness
type Role = "admin" | "editor" | "viewer";
const rolePermissions: Record<Role, string[]> = {
admin: ["read", "write", "delete"],
editor: ["read", "write"],
viewer: ["read"],
// TypeScript error if any Role is missing
// TypeScript error if you try to add an unknown key
};
Pemeriksaan keberadaan adalah manfaat utama. Ini penting ketika kunci-kunci tersebut mewakili sesuatu yang bermakna seperti peran, jenis acara, metode HTTP, atau kode status — apa pun yang di mana kehilangan kasus merupakan bug, bukan hanya kekurangan.
ReturnType — Penggunaan mingguan jika Anda menggunakan fungsi dari pihak ketiga.
Mengambil tipe hasil dari fungsi. Paling berguna ketika Anda menggunakan fungsi dari library dan ingin mengetik variabel yang menyimpan hasilnya — tanpa harus mengimpor tipe hasil secara terpisah (yang tidak selalu diekspor oleh library).
// Before: manually annotating the return type — it can drift
function getCurrentUser() {
return { id: "u1", name: "Alice", roles: ["admin"] as const };
}
let cachedUser: { id: string; name: string; roles: readonly string[] };
// If getCurrentUser's return changes, this annotation doesn't update automatically
// After: ReturnType derives it and keeps in sync
type CurrentUser = ReturnType<typeof getCurrentUser>;
let cachedUser: CurrentUser;
// Especially useful with unexported library types:
import { useQuery } from "@tanstack/react-query";
type QueryResult = ReturnType<typeof useQuery>;
// No need to figure out what QueryObserverResult<...> looks like or import it
Parameters — Penggunaan yang jarang terjadi. Terutama untuk wrapper.
Mengambil tipe parameter dari fungsi sebagai tuple. Pendekatan yang jujur: Anda tidak akan menggunakan ini setiap minggu kecuali Anda menulis banyak fungsi wrapper atau utilitas tingkat tinggi. Namun, ketika Anda membutuhkannya, tidak ada alternatif yang bersih.
// Before: manually duplicating parameter types in the wrapper
function createEvent(
type: string,
payload: Record<string, unknown>,
timestamp: number
) { /* ... */ }
// Every time createEvent changes, this wrapper needs a manual update:
function loggedCreateEvent(
type: string,
payload: Record<string, unknown>,
timestamp: number
) {
console.log("Creating event:", type);
return createEvent(type, payload, timestamp);
}
// After: Parameters keeps the wrapper in sync automatically
function loggedCreateEvent(...args: Parameters<typeof createEvent>) {
console.log("Creating event:", args[0]);
return createEvent(...args);
}
Pola penyebaran + sisa (...args: Parameters<F>) adalah idioma utama. Pola ini juga muncul dalam mock pengujian: jest.fn<ReturnType<F>, Parameters<F>>() memberi Anda mock yang sepenuhnya terstruktur tanpa harus mengimpor tanda tangan fungsi secara terpisah.
Awaited — Gunakan ketika Anda perlu menghapus tipe Promise tanpa memanggilnya.
Ditambahkan di TypeScript 4.5 (diluncurkan November 2021). Menghapus secara rekursif Promise<T> untuk mencapai T. Sebelum tersedia, mendapatkan tipe yang terurai dari fungsi asink berarti menulis tipe kondisional: ReturnType<F> extends Promise<infer U> ? U : never — yang gagal pada Promise yang dilapis dua kali dan tidak nyaman dibaca dalam perbedaan.
// Before: conditional type to unwrap — breaks on nested Promises
async function fetchUser(id: string) {
const res = await fetch(`/api/users/${id}`);
return res.json() as { id: string; name: string; email: string };
}
type FetchedUser =
ReturnType<typeof fetchUser> extends Promise<infer U> ? U : never;
// Works for Promise<T> but not Promise<Promise<T>>
// After: Awaited handles both cases cleanly
type FetchedUser = Awaited<ReturnType<typeof fetchUser>>;
// Awaited recursively unwraps:
type A = Awaited<Promise<string>>; // string
type B = Awaited<Promise<Promise<string>>>; // string
type C = Awaited<string>; // string (no-op on non-Promise)
Kombinasi Awaited<ReturnType<typeof fn>> sangat perlu dihafal sebagai satu unit — ini mencakup 90% ekstraksi tipe asink dalam kode aplikasi.
Peta cepat
| Tipe utilitas | Apa yang dilakukan | Frekuensi penggunaan | Kasus penggunaan utama |
|---|---|---|---|
Partial<T> | Semua properti menjadi opsional | Mingguan | Payload pembaruan PATCH |
Required<T> | Semua properti opsional menjadi wajib | Bulanan | Sinyal “ini lengkap” setelah validasi |
Pick<T, K> | Hanya mempertahankan properti yang disebutkan | Mingguan | Bentuk API publik, model tampilan |
Omit<T, K> | Menghapus properti yang disebutkan | Mingguan | Menghilangkan bidang sensitif atau tidak relevan |
Record<K, V> | Objek dengan kunci berjenis K dan nilai berjenis V | Mingguan | Kamus terstruktur dengan pemeriksaan keberadaan |
ReturnType<F> | Mengambil tipe hasil fungsi | Mingguan (terutama dengan library) | Mengetik variabel dari tipe yang diperkirakan atau tidak diekspor |
Parameters<F> | Mengambil tipe parameter fungsi sebagai tuple | Jarang terjadi | Fungsi wrapper, mock terstruktur |
Awaited<T> | Menghapus secara rekursif tipe Promise | Jarang terjadi | Mendapatkan tipe yang terurai dari fungsi asink |
Yang tidak ada di daftar ini
TypeScript juga menyediakan Readonly<T>, NonNullable<T>, Extract<T,U>, Exclude<T,U>, InstanceType<C>, ConstructorParameters<C>, dan beberapa tipe literal template. Mereka benar-benar ada dan kadang-kadang berguna, tetapi muncul dalam kode library, utilitas umum, dan pemrograman tingkat tipe — bukan dalam logika aplikasi biasa. Jika Anda telah menghafal delapan tipe di atas, cari tahu yang lain saat Anda benar-benar membutuhkannya.
Prinsip dasar yang sama berlaku untuk semua dari mereka: menggambarkan transformasi dari tipe yang ada, bukan menggandakan tipe tersebut. Nama-nama tipe utilitas tersebut hanyalah kosakata untuk menyampaikan niat tersebut kepada TypeScript.
Anda mungkin juga menyukai
Instal Ekstensi Kami
Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat
恵 Papan Skor Telah Tiba!
Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!
Alat Wajib Coba
Lihat semua Pendatang baru
Lihat semuaMemperbarui: Kita alat terbaru was added on Jun 26, 2026
