TypeScript Utility Types: Partial, Pick, Omit, Record and More
Utility types build new types from existing ones, so you define your data once and derive variations instead of copying fields.
interface User {
id: number;
name: string;
email: string;
role: 'admin' | 'member';
passwordHash: string;
}
Partial and Required
// All fields optional: perfect for PATCH updates
function updateUser(id: number, changes: Partial<User>) { /* ... */ }
updateUser(1, { name: 'Asha K' });
type CompleteSettings = Required<Settings>; // remove every '?'
Pick and Omit
type PublicUser = Omit<User, 'passwordHash'>; // never leak the hash
type UserPreview = Pick<User, 'id' | 'name'>; // just what a list needs
type NewUser = Omit<User, 'id'>; // id is generated by the DB
Record
type Role = User['role'];
const permissions: Record<Role, string[]> = {
admin: ['read', 'write', 'delete'],
member: ['read'],
}; // TypeScript errors if you forget a role
Readonly
const config: Readonly<{ apiUrl: string }> = { apiUrl: '/api' };
config.apiUrl = 'x'; // Error: cannot assign to 'apiUrl' because it is read-only
Types from functions
async function loadDashboard() {
return { users: 10, revenue: 52000 };
}
type Dashboard = Awaited<ReturnType<typeof loadDashboard>>; // { users: number; revenue: number }
type Args = Parameters<typeof updateUser>; // [id: number, changes: Partial<User>]
Working with unions
type Status = 'draft' | 'published' | 'archived';
type Visible = Exclude<Status, 'archived'>; // 'draft' | 'published'
type Done = Extract<Status, 'published' | 'x'>; // 'published'
type Name = NonNullable<string | null | undefined>; // string
Deriving types this way means a change to User flows everywhere automatically.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.