Logo

Home

About

Blog

Contact

Buy Merch

Portfolio

Privacy

TOS

Click to navigate

  1. Home
  2. Joshua R. Lehman's Blog
  3. Mastering TypeScript Utility Types

Table of contents

  • Share on X
  • Discuss on X

Related Articles

Basic Types in TypeScript
TypeScript
9m
Nov 23, 2025

Basic Types in TypeScript

TypeScript's type system starts with fundamental building blocks: primitive types like string, number, and boolean, along with arrays and type annotations. Understanding these basic types is essential for writing type-safe code. This comprehensive guide walks you through each primitive type, shows you how to use type annotations effectively, and teaches you best practices for working with arrays and basic data structures in TypeScript.

#TypeScript#Types+5
Object Types and Type Annotations
TypeScript
6m
Jan 7, 2026

Object Types and Type Annotations

Objects are fundamental in TypeScript. This guide covers how to define object types using inline annotations, handle nested objects, and work with object literals to ensure type safety and clarity.

#TypeScript#Objects+3
Function Overloading in TypeScript
TypeScript
9m
Dec 28, 2025

Function Overloading in TypeScript

Function overloading allows you to define multiple function signatures for a single implementation in TypeScript. This guide covers how to write overloaded functions, the implementation signature, and practical use cases to improve type safety and clarity.

#TypeScript#Functions+3
Ask me anything! 💬

© Joshua R. Lehman

Full Stack Developer

Crafted with passion • Built with modern web technologies

2026 • All rights reserved

Contents

  • Introduction to Utility Types
  • Partial<T>
  • Required<T>
  • Pick<T, K>
  • Omit<T, K>
  • Record<K, T>
  • Readonly<T>
  • Best Practices
  • Common Use Cases
  • Next Steps
TypeScript

Mastering TypeScript Utility Types

February 1, 2026•3 min read
Joshua R. Lehman
Joshua R. Lehman
Author
TypeScript Utility Types
Mastering TypeScript Utility Types

Mastering TypeScript Utility Types#

TypeScript's utility types are built-in type transformations that help you manipulate and create new types from existing ones. They're powerful tools that can significantly reduce boilerplate and improve type safety in your applications.

Introduction to Utility Types

Utility types are generic types that take existing types and transform them in useful ways. They're part of TypeScript's standard library and can be used without any additional imports.

Partial<T>

Partial<T> makes all properties of T optional:

interface User {
  id: number;
  name: string;
  email: string;
}
 
// All properties become optional
type PartialUser = Partial<User>;
 
// Now we can create objects with just some properties
const updateUser: PartialUser = {
  name: "Alice Cooper",
};

This is particularly useful for update operations where you only need to provide some fields.

Required<T>

Required<T> makes all properties of T required (opposite of Partial):

interface UserPreferences {
  theme?: "light" | "dark";
  notifications?: boolean;
  newsletter?: boolean;
}
 
// All properties become required
type MandatoryPreferences = Required<UserPreferences>;
 
const prefs: MandatoryPreferences = {
  theme: "dark",
  notifications: true,
  newsletter: false,
};

Pick<T, K>

Pick<T, K> creates a type by picking specific properties from T:

interface Product {
  id: number;
  name: string;
  price: number;
  description: string;
  category: string;
}
 
// Pick only name and price
type ProductSummary = Pick<Product, "name" | "price">;
 
const summary: ProductSummary = {
  name: "Laptop",
  price: 999.99,
};

Omit<T, K>

Omit<T, K> creates a type by omitting specific properties from T:

interface User {
  id: number;
  name: string;
  password: string;
  email: string;
}
 
// Omit sensitive password field
type PublicUser = Omit<User, "password">;
 
const publicUser: PublicUser = {
  id: 1,
  name: "Alice",
  email: "[email protected]",
  // password is not allowed here
};

Record<K, T>

Record<K, T> creates a type with keys of type K and values of type T:

// Create an object with string keys and number values
type Scores = Record<string, number>;
 
const examScores: Scores = {
  Alice: 95,
  Bob: 87,
  Charlie: 92,
};
 
// Or with specific keys
type Status = "pending" | "approved" | "rejected";
type StatusMessages = Record<Status, string>;
 
const messages: StatusMessages = {
  pending: "Your request is being reviewed",
  approved: "Your request has been approved",
  rejected: "Your request has been rejected",
};

Readonly<T>

Readonly<T> makes all properties of T readonly:

interface Config {
  apiUrl: string;
  timeout: number;
  retries: number;
}
 
type ReadonlyConfig = Readonly<Config>;
 
const config: ReadonlyConfig = {
  apiUrl: "https://api.example.com",
  timeout: 5000,
  retries: 3,
};
 
// config.timeout = 1000;
// Error: Cannot assign to 'timeout' because it is a read-only property

Best Practices

  • Use utility types to avoid duplicating type definitions
  • Combine utility types for more complex transformations
  • Prefer Pick over Omit when you need fewer properties, as it's more explicit
  • Use Partial for update operations where not all fields are required
  • Leverage Record for dictionary-like structures

Tip: You can combine utility types for more complex transformations:

// Make only specific properties optional
type UserUpdate = Partial<Pick<User, "name" | "email">>;

Common Use Cases

  1. API Responses: Use Omit to remove sensitive fields from responses
  2. Form Validation: Use Partial for form state where not all fields are filled
  3. Configuration Objects: Use Readonly for config that shouldn't change
  4. Data Transformation: Use Pick to create simplified versions of complex objects
  5. Dictionary Structures: Use Record for key-value mappings

Next Steps

Next, learn about advanced type manipulation techniques including conditional types, mapped types, and template literal types to further enhance your TypeScript skills.