Article
TypeScript Utility Types You Should Actually Use
TypeScript ships a set of built-in utility types that remove most of the hand-written generics people reach for. Here are the five I use in nearly every project.
TL;DR
Partial<T>andRequired<T>flip optionality for update payloads and config.Pick<T, K>andOmit<T, K>carve subsets out of larger types.Record<K, V>types maps and lookups cleanly.
Partial and Required
Partial<T> makes every property optional — perfect for PATCH-style update functions.
function updateUser(id: string, changes: Partial<User>) {
// changes can contain any subset of User's fields
}Required<T> does the opposite, which is handy when you resolve a config with defaults and want to guarantee nothing is left undefined.
Pick and Omit
Carve a smaller type out of a bigger one instead of redefining fields by hand.
type UserCard = Pick<User, "id" | "name" | "avatarUrl">;
type PublicUser = Omit<User, "passwordHash" | "email">;When you find yourself copy-pasting fields between interfaces, one of these is usually the answer.
Record
Record<K, V> types an object used as a map. It keeps key and value types in sync and beats reaching for any.
const labels: Record<"en" | "hi", string> = {
en: "Save",
hi: "सहेजें",
};Why prefer built-ins?
Built-in utility types are understood by every TypeScript developer, are maintained by the compiler team, and compose cleanly. A custom generic that reimplements Omit is just more surface area to get wrong.
FAQ
What is the difference between Pick and Omit? Pick keeps only the keys you list from a type, while Omit keeps everything except the keys you list. They are inverses — use whichever produces the shorter, clearer list.
Is Partial deep or shallow? Partial is shallow. It makes the top-level properties optional but leaves nested objects unchanged. For nested optionality you need a recursive DeepPartial type.