TypeScript Utility Types: Partial, Pick, Omit, Record and More

A
Author
31 Aug, 2026 1 min read 779 views

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.

Leave a comment

Comments are reviewed before they appear.