Resourcesโ€บTypeScript Tipsโ€บ10 TypeScript Utility Types You Should Actually Use
๐Ÿ“˜TypeScript Tipsโ€” 10 TypeScript Utility Types You Should Actually Useโฑ 7 min

10 TypeScript Utility Types You Should Actually Use

Stop writing repetitive type definitions. These built-in TypeScript utility types handle the patterns you keep reinventing.

๐Ÿ“…January 12, 2026โœTechTwitter.iotypescripttypesutility-types

Why Utility Types Matter

TypeScript ships with a set of built-in generic types that transform other types. Most developers know Partial and Required. Few use the full set โ€” which means they keep writing by hand what the compiler already knows how to do.

Here are the 10 that actually show up in production code.


1. Partial<T> โ€” Make All Fields Optional

interface User {
  id: string
  name: string
  email: string
}

// For update functions โ€” you don't need to send every field
function updateUser(id: string, updates: Partial<User>) { ... }

2. Required<T> โ€” Make All Fields Required

The opposite of Partial. Useful when a type has optional fields at the source but you need everything present after validation.

interface Config {
  host?: string
  port?: number
  timeout?: number
}

// After defaults are applied, everything is present
function applyDefaults(config: Config): Required<Config> {
  return {
    host: config.host ?? 'localhost',
    port: config.port ?? 3000,
    timeout: config.timeout ?? 5000,
  }
}

3. Pick<T, K> โ€” Select Specific Fields

interface User {
  id: string
  name: string
  email: string
  passwordHash: string
  createdAt: Date
}

// Never expose internal fields in API responses
type PublicUser = Pick<User, 'id' | 'name' | 'email'>

4. Omit<T, K> โ€” Remove Specific Fields

// Create without the generated fields
type CreateUserInput = Omit<User, 'id' | 'createdAt'>

function createUser(input: CreateUserInput): User { ... }

5. Record<K, V> โ€” Map of Keys to Values

Much cleaner than { [key: string]: V } and works with union keys:

type Status = 'pending' | 'active' | 'inactive'
type StatusConfig = Record<Status, { label: string; color: string }>

const config: StatusConfig = {
  pending: { label: 'Pending', color: 'yellow' },
  active: { label: 'Active', color: 'green' },
  inactive: { label: 'Inactive', color: 'gray' },
}
// TypeScript will error if you miss a status

6. Readonly<T> โ€” Prevent Mutation

function processConfig(config: Readonly<Config>) {
  // config.host = 'other' // Error: Cannot assign to 'host'
  // Forces you to create new objects instead of mutating
}

7. ReturnType<T> โ€” Extract a Function's Return Type

async function getUser(id: string) {
  return { id, name: 'Alice', role: 'admin' as const }
}

// Don't repeat yourself โ€” derive the type from the function
type UserResult = Awaited<ReturnType<typeof getUser>>
// { id: string; name: string; role: 'admin' }

This is invaluable when the return type is complex and you don't want to define it separately.


8. Parameters<T> โ€” Extract Function Parameters

function createOrder(userId: string, items: Item[], coupon?: string) { ... }

type OrderParams = Parameters<typeof createOrder>
// [userId: string, items: Item[], coupon?: string]

// Useful for wrapper/middleware functions
function loggedCreateOrder(...args: Parameters<typeof createOrder>) {
  console.log('Creating order:', args)
  return createOrder(...args)
}

9. NonNullable<T> โ€” Remove null and undefined

type MaybeUser = User | null | undefined

// After you've checked it's not null
type DefiniteUser = NonNullable<MaybeUser> // User

10. Extract<T, U> and Exclude<T, U>

type EventType = 'click' | 'hover' | 'focus' | 'blur' | 'keydown'

// Only keyboard events
type KeyboardEvent = Extract<EventType, 'keydown' | 'keyup'>
// 'keydown'

// Everything except keyboard events
type MouseEvent = Exclude<EventType, 'keydown' | 'keyup'>
// 'click' | 'hover' | 'focus' | 'blur'

Combining Utility Types

The real power comes from combining them:

// Read-only partial update (safe config merge)
type SafeConfigUpdate = Readonly<Partial<Config>>

// API response without sensitive fields, all required
type ApiUser = Required<Omit<User, 'passwordHash' | 'internalNotes'>>

// Function that accepts any subset of User fields
function updateProfile(userId: string, data: Partial<Pick<User, 'name' | 'email'>>) { ... }

Key Takeaways

  • Partial / Required โ€” toggle field optionality
  • Pick / Omit โ€” select or remove fields
  • Record โ€” typed key-value maps (great with union keys)
  • ReturnType / Parameters โ€” derive types from functions
  • Combine them โ€” the real utility comes from composition