Skip to main content
Tutorial

My TypeScript Utility Types Cheatsheet for Real-World Projects

5 min read

A practical guide to TypeScript utility types like Partial, Omit, Pick, and Record with real-world examples from UAE-based projects.

TypeScriptJavaScriptUtility TypesLaravelNext.js

I was debugging a form submission in a Next.js app last month for a Saudi e-commerce client when I ran face-first into the classic Partial problem. The form API only accepted undefined for empty fields, but my React component was sending empty strings. A teammate suggested wrapping the entire form state with Partial, which worked but broke validation logic elsewhere. Turns out, you don’t always want all properties optional — just specific ones. That’s when I remembered the rest of TypeScript’s utility types exist to save you from writing 100 lines of redundant interfaces.


When `Partial` Isn’t Actually Partial Enough

Most tutorials show Partial making every property optional, but real-world usage is messier. Imagine a user profile with username, email, and phoneNumber. If you’re writing an API that only allows updating one field at a time, using Partial would technically let someone submit all three — which isn’t what you want.

I learned this the hard way in a Dubai fintech app where a user could accidentally overwrite their phone number while changing their email. The fix? Combine Partial with record types for stricter one-at-a-time updates:

ts
type SingleUpdate = Partial<{  
  [Key in keyof User]: Record<Key, User[Key]>;  
}>;  

This way, a developer can only update username or email or phoneNumber, not multiple fields. It felt like overkill initially, but the client insisted on preventing accidental data overwrites in their Arabic/English bilingual platform — and honestly, they were right to.


`Omit` vs `Pick`: Choosing the Right Side of the Coin

I use Omit when I know what I don’t want, and Pick when I know what I do. Recently, while building a property listing API for a UAE real estate client, I needed to exclude privateNotes and internalStatus from public property cards. So:

ts
const publicProperty = (property: PropertyEntity): Omit<PropertyEntity, 'privateNotes' | 'internalStatus'> => ({  
  // ...all other properties  
});  

Compare that to a React component in Tawasul Limo’s booking flow where only ar.firstName, ar.lastName, en.firstName, and en.lastName were needed from a larger user object. Instead of listing 15 irrelevant keys to omit, Pick made more sense:

ts
type NameTranslations = Pick<User, 'ar.firstName' | 'ar.lastName' | 'en.firstName' | 'en.lastName'>;  

One time in an Expo app, I accidentally used Omit with a string union from an enum — TypeScript didn’t complain until runtime. So now I always double-check key names manually. Yeah, it’s a footgun 🙃


`Record` for When Objects Aren’t About Data

Use Record when the shape of the object matters more than specific keys. For example, Greeny Corner’s plant care API has language support for English and Arabic. Every plant entry includes translations, which must have both languages but allow any plant-specific fields:

ts
type Translations = Record<'en' | 'ar', {  
  commonName: string;  
  careTips: string;  
  // ...etc  
}>;  

But don’t get lazy with Record. I did that once in a Firebase function for a logistics app, and it turned into a debugging nightmare — turns out, not every key was supposed to be numeric. Better to explicitly define:

ts
// Horrible idea:  
type Shipments = Record<string, ShipmentData>;  

// Better version:  
type Shipments = Record<RegionCode, ShipmentData>;  
// where RegionCode is "DXB" | "RUH" | "AUH" | ...  

Real-World Example: Filtering Dashboard Columns

Last summer, I built a user analytics dashboard for a Riyadh bank that let admins choose visible columns. The backend response included 30+ fields, but the UI only needed 8-10 based on user preferences.

I combined Pick and Omit to create types for different roles:

ts
type BaseFields = 'userId' | 'createdAt' | 'lastLogin';  
type AdminOnly = 'loginAsUser' | 'accountStatus';  

type DashboardUser<T extends string> = Pick<User, BaseFields> & Partial<Record<T, User[T]>>;  

// Admin view  
type AdminView = DashboardUser<AdminOnly>;  

// Auditor view (no sensitive fields)  
type AuditorView = Omit<DashboardUser<AdminOnly>, AdminOnly>;  

This let us reuse core fields while ensuring role-based constraints — and yeah, it saved 20+ hours of type maintenance across 40+ pages.


Frequently Asked Questions

What's the difference between `Pick` and `Omit`?

Pick explicitly selects keys you want, Omit drops keys you don’t. Use Pick for small, specific sets (like user names in Tawasul Limo’s booking form) and Omit when excluding a few fields from a large object (like hiding internal status in property listings for Abu Dhabi real estate).

Can I use `Record` with dynamic keys?

Technically yes, but it defeats the purpose. TypeScript won’t enforce type safety for keys you compute at runtime. If you need dynamic keys, consider a Map or reduce function instead.

Why does `Partial` sometimes break validation?

Because it uses undefined to make properties optional, not null or empty strings. If your API expects empty strings for missing data (common in legacy PHP/Laravel apps I’ve worked on), Partial-generated objects will fail backend validation.

Is it okay to nest `Omit` or `Pick`?

If you find yourself nesting more than twice, step back. Either flatten the data structure or create an explicit interface. Over-nesting leads to types like Omit, 'email'> which defeats readability — and in my experience, comes back to bite during refactor sprints.


I’ve written 40+ projects in the UAE and GCC over 7 years, and the one thing I’m convinced of? The right utility type can save hours of manual interface work — if you know which one to use when the code feels messy. If you’re working on a Laravel+Next.js app with Arabic language support, or a React Native project with Expo modules — yeah, I’ve been there. You can book a free consultation if you need help untangling your TypeScript architecture.

S

Sarah

Senior Full-Stack Developer & PMP-Certified Project Lead — Abu Dhabi, UAE

7+ years building web applications for UAE & GCC businesses. Specialising in Laravel, Next.js, and Arabic RTL development.

Work with Sarah