TypeScript includes powerful built-in utility types that transform existing types in useful ways. These utilities help you avoid repetition and create flexible type definitions.
Makes all properties optional. Perfect for update functions:
interface Player {
name: string;
health: number;
level: number;
experience: number;
}
// Update only some properties
function updatePlayer(
player: Player,
updates: Partial<Player>
): Player {
return { ...player, ...updates };
}
const hero: Player = {
name: "Hero",
health: 100,
level: 5,
experience: 1200
};
// Update only health and experience
const updated = updatePlayer(hero, {
health: 80,
experience: 1350
});
Makes all properties required (opposite of Partial):
interface GameConfig {
difficulty?: string;
sound?: boolean;
graphics?: string;
}
// Function requires all config options
function initializeGame(config: Required<GameConfig>): void {
console.log(`Difficulty: ${config.difficulty}`);
console.log(`Sound: ${config.sound}`);
console.log(`Graphics: ${config.graphics}`);
}
initializeGame({
difficulty: "normal",
sound: true,
graphics: "high"
}); // All required!
// initializeGame({ difficulty: "easy" }); // ✗ Error - missing properties
Makes all properties readonly (immutable):
interface Point {
x: number;
y: number;
}
const mutablePoint: Point = { x: 10, y: 20 };
mutablePoint.x = 15; // ✓ OK
const immutable Point: Readonly<Point> = { x: 10, y: 20 };
// immutablePoint.x = 15; // ✗ Error - readonly property
// Useful for function parameters
function calculateDistance(
p1: Readonly<Point>,
p2: Readonly<Point>
): number {
const dx = p2.x - p1.x;
const dy = p2.y - p1.y;
return Math.sqrt(dx * dx + dy * dy);
}
Creates a type by picking specific properties from another type:
interface User {
id: number;
username: string;
email: string;
password: string;
createdAt: Date;
updatedAt: Date;
}
// Pick only public-facing properties
type PublicUser = Pick<User, "id" | "username" | "createdAt">;
// Equivalent to:
// type PublicUser = {
// id: number;
// username: string;
// createdAt: Date;
// }
function displayUser(user: PublicUser): void {
console.log(`${user.username} (ID: ${user.id})`);
// Cannot access user.email or user.password (not in type)
}
Creates a type by omitting specific properties (opposite of Pick):
interface Product {
id: number;
name: string;
price: number;
description: string;
stock: number;
internalNotes: string;
}
// Omit sensitive internal properties
type PublicProduct = Omit<Product, "internalNotes" | "stock">;
// Equivalent to:
// type PublicProduct = {
// id: number;
// name: string;
// price: number;
// description: string;
// }
function displayProduct(product: PublicProduct): void {
console.log(`${product.name}: $${product.price}`);
}
// Useful for creating types without certain properties
type UserWithoutPassword = Omit<User, "password">;
Creates an object type with specific keys and value types:
// Map string keys to numbers
type Scores = Record<string, number>;
const gameScores: Scores = {
"player1": 1500,
"player2": 2300,
"player3": 1800
};
// Map specific keys to a type
type PageInfo = {
title: string;
description: string;
};
type SitePages = Record<"home" | "about" | "contact", PageInfo>;
const pages: SitePages = {
home: { title: "Home", description: "Welcome page" },
about: { title: "About", description: "About us" },
contact: { title: "Contact", description: "Get in touch" }
};
// Useful for creating lookup objects
type HttpStatus = Record<number, string>;
const statusMessages: HttpStatus = {
200: "OK",
404: "Not Found",
500: "Server Error"
};
Work with union types to include or exclude members:
type AllEvents = "click" | "scroll" | "mousemove" | "keypress";
// Exclude specific members
type UIEvents = Exclude<AllEvents, "scroll" | "mousemove">;
// Result: "click" | "keypress"
// Extract specific members
type MouseEvents = Extract<AllEvents, "click" | "mousemove">;
// Result: "click" | "mousemove"
// Exclude null and undefined
type NoNullable<T> = Exclude<T, null | undefined>;
type MaybeString = string | null | undefined;
type DefiniteString = NoNullable<MaybeString>; // string
Extract types from function signatures:
// Get the return type of a function
function createPlayer(name: string, level: number) {
return {
name,
level,
health: 100,
isAlive: true
};
}
type Player = ReturnType<typeof createPlayer>;
// Player = { name: string; level: number; health: number; isAlive: boolean; }
// Get parameter types of a function
type CreatePlayerParams = Parameters<typeof createPlayer>;
// CreatePlayerParams = [name: string, level: number]
function callWithArgs(
fn: typeof createPlayer,
...args: Parameters<typeof createPlayer>
) {
return fn(...args);
}
const player = callWithArgs(createPlayer, "Hero", 5);
interface CompleteUser {
id: number;
username: string;
email: string;
password: string;
profile: {
age?: number;
bio?: string;
};
settings: {
theme: string;
notifications: boolean;
};
}
// Partial user for updates, but ID is required
type UserUpdate = Partial<Omit<CompleteUser, "id">> & Pick<CompleteUser, "id">;
// Public user: omit password, make everything readonly
type PublicUser = Readonly<Omit<CompleteUser, "password">>;
// New user registration (no ID yet, password required)
type UserRegistration = Omit<CompleteUser, "id"> & {
passwordConfirm: string;
};
Partial<T> - all properties optionalRequired<T> - all properties requiredReadonly<T> - all properties immutablePick<T, K> - select specific properties
Omit<T, K> - remove specific properties
Record<K, T> - object type with specific keys