Master TypeScript Like a Pro: extends, Pick & Omit (Most Developers Use Them Wrong)
If you’re using TypeScript daily but still writing duplicate interfaces…
👉 You’re working harder than necessary.
TypeScript already gives you powerful tools to reshape types instantly without rewriting code.
Today we’re mastering three essentials:
✅ extends — build smarter inheritance
✅ Pick — select only what you need
✅ Omit — remove dangerous or unnecessary fields
Think of these as your TypeScript Swiss Army Knife.
Once you understand these properly, your API types, DTOs, and frontend models become clean, scalable, and DRY.
🤔 Why Utility Types Matter (Real Developer Problem)
Imagine this:
You have a large User type with 20+ fields.
But:
👉 Your update API needs only 3 fields
👉 Your frontend must NOT receive passwords
👉 Admin users need extra properties
Without utility types:
❌ Duplicate interfaces
❌ Maintenance nightmare
❌ Bugs when properties change
With utility types:
✅ One source of truth
✅ Safer refactoring
✅ Cleaner architecture
🧩 1. extends — Type Inheritance Superpower
extends lets you build specialized types from a base type.
Perfect for:
- role-based models
- admin dashboards
- feature variations
Example
interface User {
id: string;
name: string;
email: string;
role: 'user' | 'admin';
createdAt: Date;
}
interface Admin extends User {
permissions: string[];
canDeleteUsers: boolean;
}🔥 Real-world example:
- Base
Project - Extend to
PremiumProject - Add advanced limits or analytics
No duplication. Fully scalable.
🎯 2. Pick — Select Only What You Need
Pick is extremely useful for:
✅ API payloads
✅ Form submissions
✅ DTOs (NestJS lovers 👀)
Example:
interface User {
id: string;
name: string;
email: string;
password: string;
role: 'user' | 'admin';
}
type UpdateUserPayload = Pick<User, 'name' | 'email'>;Now TypeScript enforces:
✔ Only allowed fields
❌ No accidental password updates
Senior-level tip:
type Clone<T> = Pick<T, keyof T>;✂️ 3. Omit — Remove Sensitive Data Instantly
Opposite of Pick.
Use when:
- sending data to frontend
- hiding sensitive properties
- building public API responses
type PublicUserProfile = Omit<User, 'password' | 'role'>;This prevents security mistakes automatically.
⚡ The Real Power: Combine Them
Advanced developers rarely use just one.
Example:
type AdminUpdatePayload = Pick<
Omit<User, 'password'> & { permissions: string[] },
'name' | 'email' | 'permissions'
>;Now you:
✔ Remove sensitive data
✔ Add new fields
✔ Select only required properties
All without rewriting interfaces.
🧠 Quick Mental Model
| Tool | Think Like |
|---|---|
| extends | child inherits parent |
| Pick | filter selected keys |
| Omit | exclude unwanted keys |
🔥 Real Production Use Cases
NestJS DTOs
type CreateUserDto = Pick<User, 'name' | 'email'>Next.js API Response
type SafeUser = Omit<User, 'password'>Role-based Permissions
interface Admin extends User {}⚠️ Common Pitfalls
👉 Pick and Omit are shallow (not deep nested).
👉 They preserve optional fields automatically.
👉 Works great with union types.
💥 Senior Developer Trick
Create reusable utilities:
type WithoutId<T> = Omit<T, 'id'>;Now your code becomes reusable and scalable.
🏆 Final Thoughts
Most developers learn TypeScript types…
But senior developers compose types.
Once you start using:
✅ extends
✅ Pick
✅ Omit
You stop writing duplicate interfaces forever.
🔥 Challenge:
Open your current project.
Find one duplicated interface.
Refactor it using utility types.
Your future self will thank you.
If this helped you:
👉 Save it for later
👉 Share with a TypeScript learner
👉 Drop your favourite utility type below 😎
🔥 Bonus (real growth advice for you Ajay)
Your writing style is already strong — you just needed:
✅ stronger hook
✅ clearer authority tone
✅ production examples
✅ developer psychology triggers