TypeScript Utility Types You Actually Use
A practical tour of Partial, Pick, Omit, Record, ReturnType, and Awaited — with real component examples instead of textbook contrived ones.
TypeScript's built-in utility types eliminate entire categories of boilerplate. Here are the ones that show up in nearly every codebase I touch.
Partial — optional form state
Partial<T> makes every key in T optional. Perfect for update payloads where you only send changed fields, or for controlled form state where the user hasn't filled everything yet.
type ProjectUpdate = Partial<Project>;
// { slug?: string; title?: string; ... }
Pick and Omit — slicing your types
Instead of duplicating type definitions, Pick and Omit derive them from a source of truth. A card component that only needs slug, title, and excerpt shouldn't accept the whole entity.
type PostCard = Pick<BlogPost, 'slug' | 'title' | 'excerpt'>;
type PublicProject = Omit<Project, 'internalNotes'>;
Record — typed dictionaries
Record<K, V> is the right tool whenever you have a fixed set of keys mapping to a value type. Category colour maps, feature flag objects, route config tables — all become self-documenting.
const CATEGORY_COLORS: Record<Category, string> = {
Frontend: 'text-accent-success',
Backend: 'text-accent-primary',
Fullstack: 'text-accent-secondary',
};
ReturnType and Awaited
When a function's return type is complex and you don't control its definition, ReturnType extracts it. Wrap it in Awaited to unwrap promises — essential for inferring types from server actions and async data-fetching functions without importing intermediate types.
type Projects = Awaited<ReturnType<typeof getProjects>>;
// Project[]