How to Use Utility Types in TypeScript
What you’ll build or solve
You’ll create derived types such as partial updates, read-only versions, or selected subsets of properties.
When this approach works best
Utility types work best when you:
Learn TypeScript on Mimo
- Build forms where only some fields are required
- Create update functions that accept partial data
- Expose read-only versions of internal models
They also help when you want to reuse a base interface in multiple variations.
This is a bad idea if your types are already small and unlikely to change. In simple cases, writing a new interface may be clearer.
Prerequisites
- TypeScript installed
- A
.tsfile - Basic knowledge of interfaces and type aliases
Step-by-step instructions
Step 1: Use Partial to make properties optional
Partial<T> makes all properties in a type optional.
interfaceUser {
id:number;
name:string;
email:string;
}
typeUserUpdate=Partial<User>;
Now every property in UserUpdate is optional.
CSS
constupdate:UserUpdate= {
name:"Alex"
};
Step 2: Use Required to make properties mandatory
Required<T> makes all properties required, even if they were optional.
interfaceSettings {
theme?:string;
notifications?:boolean;
}
typeCompleteSettings=Required<Settings>;
constsettings:CompleteSettings= {
theme:"dark",
notifications:true
};
Step 3: Use Readonly to prevent reassignment
Readonly<T> marks all properties as read-only.
interfaceProduct {
id:number;
price:number;
}
typeReadonlyProduct=Readonly<Product>;
constitem:ReadonlyProduct= {
id:1,
price:100
};
item.price=200;// Error
Step 4: Use Pick to select specific properties
Pick<T, K> creates a new type with only selected keys.
interfaceUser {
id:number;
name:string;
email:string;
}
typeUserPreview=Pick<User,"id"|"name">;
constpreview:UserPreview= {
id:1,
name:"Jordan"
};
Step 5: Use Omit to remove specific properties
Omit<T, K> removes selected keys from a type.
interfaceUser {
id:number;
name:string;
password:string;
}
typePublicUser=Omit<User,"password">;
constuser:PublicUser= {
id:1,
name:"Sam"
};
Step 6: Use Record to define object maps
Record<K, T> creates an object type with specific keys and value types.
typeRoles="admin"|"editor"|"viewer";
typePermissions=Record<Roles,boolean>;
constpermissions:Permissions= {
admin:true,
editor:false,
viewer:true
};
What to look for
- Utility types wrap an existing type inside angle brackets
- They do not modify the original interface
- Combine utilities for more specific shapes, for example
Partial<Omit<User, "password">> - Utility types affect compile-time checks only,
Readonlydoes not block runtime mutation - Prefer reusing base types instead of duplicating interfaces
Examples you can copy
Example 1: Update function with Partial
PHP
interfaceProfile {
username:string;
bio:string;
avatarUrl:string;
}
functionupdateProfile(id:number,updates:Partial<Profile>) {
return { id, ...updates };
}
Example 2: Public API response with Omit
interfaceAccount {
id:number;
email:string;
password:string;
}
typePublicAccount=Omit<Account,"password">;
functiongetPublicAccount(account:Account):PublicAccount {
const { password, ...rest }=account;
returnrest;
}
If you also need a “patch” shape for updates, combine utilities:
typePublicAccountUpdate=Partial<Omit<Account,"password">>;
Example 3: Feature flags with Record
typeFeature="darkMode"|"betaAccess";
typeFeatureFlags=Record<Feature,boolean>;
constflags:FeatureFlags= {
darkMode:true,
betaAccess:false
};
Common mistakes and how to fix them
Mistake 1: Duplicating types instead of using utilities
You might write:
CSS
interfaceUserUpdate {
id?:number;
name?:string;
email?:string;
}
Why it breaks: When User changes, this copy can fall out of sync.
Correct approach:
typeUserUpdate=Partial<User>;
Mistake 2: Expecting utility types to change runtime behavior
You might write:
constproduct:Readonly<Product>= { id:1, price:50 };
product.price=60;
Why it breaks: Utility types affect compile-time checks only, not runtime behavior.
Correct approach: Keep the object immutable in your code. If you need mutation, use the base type or create a copy.
Troubleshooting
- If TypeScript says a property is missing, confirm you are not using
Required. - If a property becomes optional unexpectedly, check for
Partial. - If a field is not available, confirm it was removed using
Omitor excluded fromPick. - If a map object shows key errors, verify the union type used in
Record.
Quick recap
Partialmakes all properties optionalRequiredmakes all properties mandatoryReadonlyprevents reassignmentPickselects specific keysOmitremoves specific keysRecordcreates typed key-value maps
Join 35M+ people learning for free on Mimo
4.8 out of 5 across 1M+ reviews
Check us out on Apple AppStore, Google Play Store, and Trustpilot