Utility Types
Utility types are ready-made type transformations built into TypeScript. They let you create “a User but every field optional” or “a User without the password” in one line.
On this page · 5 min · Advanced
On this page
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Advanced
- Updated
- Oct 28, 2026
Related tutorials
Learning objectives#
- Transform object types with Partial, Required, Readonly
- Select properties with Pick and Omit
- Build dictionaries with Record
- Filter unions with Exclude, Extract and NonNullable
- Read function types with ReturnType, Parameters and Awaited
Explanation#
Partial<T> makes every property optional (great for update/patch payloads). Required<T> does the opposite. Readonly<T> makes all properties read-only.
Pick<T, "a" | "b"> keeps only those keys; Omit<T, "password"> removes keys.
Record<K, V> builds an object type with keys K and values V: Record<Role, string[]>.
Union filters: Exclude<U, X> removes members, Extract<U, X> keeps matching ones, NonNullable<T> removes null and undefined.
Function helpers: ReturnType<typeof fn>, Parameters<typeof fn>, and Awaited<T> unwraps a Promise type.
Syntax#
type UserUpdate = Partial<User>;
type PublicUser = Omit<User, 'password'>;
type Preview = Pick<User, 'id' | 'name'>;
Code example: One model, many derived types#
interface User {
id: number;
name: string;
email: string;
password: string;
role: 'admin' | 'editor' | 'viewer';
}
type NewUser = Omit<User, 'id'>; // for create forms
type UserUpdate = Partial<Omit<User, 'id'>>; // for PATCH requests
type PublicUser = Omit<User, 'password'>; // safe to send to the client
type UserPreview = Pick<User, 'id' | 'name'>; // for lists
type Role = User['role'];
type Permissions = Record<Role, string[]>;
const permissions: Permissions = {
admin: ['*'],
editor: ['posts:write'],
viewer: ['posts:read'],
}; // ✗ if any role is missing
type NonAdmin = Exclude<Role, 'admin'>; // 'editor' | 'viewer'
type MaybeEmail = string | null | undefined;
type Email = NonNullable<MaybeEmail>; // string
async function fetchUser(id: number): Promise<PublicUser> {
return { id, name: 'Asha', email: 'a@x.in', role: 'viewer' };
}
type FetchArgs = Parameters<typeof fetchUser>; // [id: number]
type Fetched = Awaited<ReturnType<typeof fetchUser>>; // PublicUser
function updateUser(id: number, changes: UserUpdate) { /* … */ }
updateUser(1, { name: 'Asha V' }); // ✓ only what changed
updateUser(1, { id: 9 }); // ✗ 'id' does not exist in type 'Partial<Omit<User, "id">>'
All derived types follow the User interface automatically. updateUser accepts partial changes but rejects changing the id; the Permissions object must list every role.
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- Omit<User, "id"> describes data for creating a user (the database assigns the id).
- Partial<Omit<…>> allows sending only changed fields.
- PublicUser removes the password before data leaves the server.
- Record<Role, string[]> forces a permissions entry for every role.
- Exclude and NonNullable filter unions.
- Parameters, ReturnType and Awaited read types from an existing function.
Real-world use case#
API layers define one entity type and derive DTOs from it: CreateDto = Omit<T, "id">, UpdateDto = Partial<CreateDto>, ResponseDto = Omit<T, "password">.
Common mistakes#
Writing a second UserWithoutPassword by hand means two places to update. Derive it with Omit.
Partial only makes top-level properties optional. Nested objects stay required.
Omit<User, "pasword"> silently omits nothing. Double-check keys (or use a stricter custom helper).
Best practices#
- Keep one source model and derive DTOs with utility types
- Use Record<Union, V> to force exhaustive maps
- Use Awaited<ReturnType<typeof fn>> instead of re-declaring result types
- Combine utilities, but name the result for readability
Remember this#
Partial = all optional. Required = all required. Readonly = all frozen.
Pick = keep these. Omit = drop these.
Record<Keys, Value> = a complete lookup table.
Practice exercise#
Your task: Given interface Product { id: number; name: string; price: number; stock: number }, create: ProductForm (no id), ProductPatch (all form fields optional) and StockMap (Record of product name to stock).
Need a hint?
Show solution
interface Product { id: number; name: string; price: number; stock: number }
type ProductForm = Omit<Product, 'id'>;
type ProductPatch = Partial<ProductForm>;
type StockMap = Record<Product['name'], Product['stock']>; // Record<string, number>
Mini quiz#
Which utility removes the password property from User?
Want more? Practise all TypeScript MCQs · TypeScript interview questions
My notes#
Saved in this browser.