Module lessons (2/2)
Utility Types
TypeScript provides several global utility types to facilitate common type transformations. These types are generic and allow you to declaratively build new types from existing ones.
The four most commonly used utility types are:
1. Partial<T>
Makes all properties of a type T optional. This is extremely useful for update/patch functions where the caller might only supply a subset of fields:
interface User {
id: number;
name: string;
email: string;
}
// All properties of User become optional: { id?: number; name?: string; email?: string; }
type UserUpdate = Partial<User>;2. Readonly<T>
Makes all properties of a type T readonly. Any attempt to reassign a property will trigger a compile-time compiler error:
interface Point {
x: number;
y: number;
}
const p: Readonly<Point> = { x: 10, y: 20 };
// p.x = 5; // Error: cannot assign to 'x' because it is a read-only property3. Pick<T, Keys>
Creates a type by selecting only a specific set of keys (represented by a string union) from the type T:
interface Article {
id: number;
title: string;
content: string;
views: number;
}
// Selects only 'title' and 'views': { title: string; views: number; }
type ArticlePreview = Pick<Article, 'title' | 'views'>;4. Omit<T, Keys>
Creates a type by removing a specific set of keys from the type T. It is the dual of Pick:
interface Product {
id: number;
name: string;
price: number;
secretVendorCode: string;
}
// Removes 'secretVendorCode': { id: number; name: string; price: number; }
type PublicProduct = Omit<Product, 'secretVendorCode'>;5. Record<Keys, Type>
Creates an object type whose property keys are Keys and whose property values are Type. It is extremely useful for mapping keys to values, representing dictionaries or hash tables (key-value maps):
type Page = 'home' | 'about' | 'contact';
interface PageInfo {
title: string;
}
// Creates a dictionary with keys 'home' | 'about' | 'contact' and values PageInfo
const nav: Record<Page, PageInfo> = {
home: { title: 'Home Page' },
about: { title: 'About Us' },
contact: { title: 'Contact Us' },
};Try it yourself
Exercise 1: Profile Update with Partial
Complete the updateProfile function that accepts an original profile (Profile) and an updates object (updates) where all fields of Profile are optional. It must return a new Profile object combining the original properties with the updates.
Show hint
Use the Partial<Profile> utility type for the updates parameter, and the spread operator to merge the objects: { ...original, ...updates }.
Solution available after 3 attempts
Exercise 2: Removing Sensitive Fields with Omit
Given the UserAccount type, define a type alias named SafeUser that omits the sensitive passwordHash property.
Show hint
Use type SafeUser = Omit<UserAccount, 'passwordHash'>; to omit the specified field.
Solution available after 3 attempts
Exercise 3: Public Config with Pick and Readonly
Given the AppConfig type, define a type alias named PublicConfig that is a read-only (Readonly) version containing only the apiEndpoint and port properties selected using Pick.
Show hint
Use type PublicConfig = Readonly<Pick<AppConfig, 'apiEndpoint' | 'port'>>;
Solution available after 3 attempts
Exercise 4: User Registry with Record and Readonly
Given a User interface with fields id: number and name: string, create a type ReadOnlyUser that makes all fields in User readonly. Then, create a type UserRegistry that represents a dictionary where the key is a string (e.g., string id) and the value is a ReadOnlyUser.
Show hint
Use Readonly<User> to define ReadOnlyUser, and Record<string, ReadOnlyUser> for the registry.
Solution available after 3 attempts