TypeScript: TypeScript Utility Types
Last updated: 2026-08-26
TypeScript includes more than a dozen utility types—these represent best practices in generic programming and allow you to perform common type conversions with a single line of code.
1. Property Transformation Class
(1) Partial—All properties become optional
TYPESCRIPT
interface User {
id: number;
name: string;
email: string;
age: number;
}
// Partial Make all properties optional——Suitable for update operations
type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; age?: number }
function updateUser(user: User, updates: Partial<User>): User {
return { ...user, ...updates };
}
let user: User = { id: 1, name: "Charlie", email: "xiao@example.com", age: 20 };
let updated = updateUser(user, { age: 21 });
// Update Only age,All other attributes remain unchanged
console.log(updated.age); // 21
console.log(updated.name); // "Charlie"(Unchanged)
(2) Required—All properties are now required
TYPESCRIPT
interface Config {
host?: string;
port?: number;
debug?: boolean;
}
// Required Make all fields required——Suitable for verifying logic
type RequiredConfig = Required<Config>;
// { host: string; port: number; debug: boolean }
function validateConfig(config: RequiredConfig): void {
console.log(`${config.host}:${config.port} (debug: ${config.debug})`);
}
(3) Readonly—All properties become read-only
TYPESCRIPT
interface Point {
x: number;
y: number;
}
// Readonly Make all properties read-only
type ReadonlyPoint = Readonly<Point>;
// { readonly x: number; readonly y: number }
let point: ReadonlyPoint = { x: 1, y: 2 };
// point.x = 10; // ❌ Read-only properties cannot be modified.
// Common Uses:Function Parameter Protection
function freezeConfig(config: Readonly<Config>): void {
// config.host = "other"; // ❌ Modifications are not allowed.
console.log("Configuration Frozen");
}
▶ Example: CRUD Type Conversion
Output:
TEXT
📖 Display only
Create: TypeScript Getting Started
Update: TypeScript Advanced
Abstract: TypeScript Getting Started
TYPESCRIPT
interface Article {
id: number;
title: string;
content: string;
author: string;
createdAt: Date;
updatedAt: Date;
}
// At the time of creation:Not necessary id and timestamps
type CreateArticle = Omit<Article, "id" | "createdAt" | "updatedAt">;
// When updating:All fields are optional
type UpdateArticle = Partial<Omit<Article, "id" | "createdAt">>;
// List View:Show only some fields
type ArticleSummary = Pick<Article, "id" | "title" | "author" | "createdAt">;
// Create
let newArticle: CreateArticle = {
title: "TypeScriptGetting Started",
content: "TypeScript is a superset of JavaScript...",
author: "Charlie"
};
// Update
let updateData: UpdateArticle = {
title: "TypeScript Advanced",
content: "An In-Depth Understanding of Generics..."
};
// List
let summary: ArticleSummary = {
id: 1,
title: "TypeScriptGetting Started",
author: "Charlie",
createdAt: new Date()
};
console.log("Create:" + newArticle.title);
console.log("Update:" + (updateData.title ?? "No changes"));
console.log("Abstract:" + summary.title);
Output:
TEXT
📖 Display only
Create:TypeScriptGetting Started
Update:TypeScript Advanced
Abstract:TypeScriptGetting Started
2. Attribute Selection Class
(1) Pick—Select certain attributes
TYPESCRIPT
interface User {
id: number;
name: string;
email: string;
password: string;
role: string;
}
// Pick Select the specified property
type UserPublic = Pick<User, "id" | "name" | "email">;
// { id: number; name: string; email: string }
let publicProfile: UserPublic = {
id: 1,
name: "Charlie",
email: "xiao@example.com"
};
// None password and role —— Safely Disclosing Public Information
(2) Omit—Exclude certain attributes
TYPESCRIPT
// Omit Exclude the specified properties(Pick the opposite of)
type UserSafe = Omit<User, "password">;
// { id: number; name: string; email: string; role: string }
let safeUser: UserSafe = {
id: 1,
name: "Charlie",
email: "xiao@example.com",
role: "admin"
};
// password Excluded
(3) Pick vs. Omit: Choosing
TYPESCRIPT
// Retain a few properties → Pick More concise
type Mini = Pick<User, "id" | "name">; // 2a property → Pick
// Exclude a few attributes → Omit More concise
type NoPassword = Omit<User, "password">; // Exclusion1 → Omit
// Preserve Most Properties → Omit More concise
type AlmostAll = Omit<User, "password">; // Retain4 → Omit
// Exclude Most Attributes → Pick More concise
type OnlyTwo = Pick<User, "id" | "name">; // Exclusion3 → Pick
3. Union Type Operation Classes
(1) Exclude—Exclude from the union type
TYPESCRIPT
type AllTypes = "a" | "b" | "c" | "d";
// Exclude Exclude Specified Members
type WithoutA = Exclude<AllTypes, "a">; // "b" | "c" | "d"
type WithoutAB = Exclude<AllTypes, "a" | "b">; // "c" | "d"
(2) Extract—Extracting from a union type
TYPESCRIPT
type Mixed = string | number | boolean | null;
// Extract Extract Specified Members
type OnlyString = Extract<Mixed, string>; // string
type StringOrNumber = Extract<Mixed, string | number>; // string | number
(3) NonNullable — Exclude null and undefined
TYPESCRIPT
type MaybeString = string | null | undefined;
// NonNullable Exclusion null and undefined
type DefiniteString = NonNullable<MaybeString>; // string
▶ Example: Filtering Invalid Values
Output:
TEXT
📖 Display only
Handling Events: click
Handling Events: focus
TYPESCRIPT
type EventName = "click" | "focus" | "blur" | null | undefined;
// Exclusion null and undefined
type ValidEvent = NonNullable<EventName>; // "click" | "focus" | "blur"
// Keep only mouse events
type MouseEvent = Extract<ValidEvent, "click">; // "click"
// Exclusion click Unforeseen events
type NonClick = Exclude<ValidEvent, "click">; // "focus" | "blur"
function handleEvent(event: ValidEvent): void {
console.log(`Handling Events:${event}`);
}
handleEvent("click"); // ✅
handleEvent("focus"); // ✅
// handleEvent(null); // ❌ NonNullable Ruled out
Output:
TEXT
📖 Display only
Handling Events:click
Handling Events:focus
4. Function-Type Operation Classes
(1) ReturnType—Get the function's return type
TYPESCRIPT
function createUser(name: string, age: number) {
return { name, age, active: true };
}
// ReturnType Get the return type——No handwriting required
type User = ReturnType<typeof createUser>;
// { name: string; age: number; active: boolean }
let user: User = { name: "Diana", age: 22, active: false };
(2) Parameters—Retrieve a tuple of function parameter types
TYPESCRIPT
function register(name: string, email: string, age: number): void {}
// Parameters Get Parameter Type
type RegisterParams = Parameters<typeof register>;
// [string, string, number]
let params: RegisterParams = ["Charlie", "xiao@example.com", 20];
(3) ConstructorParameters—Get the types of constructor parameters
TYPESCRIPT
class Point {
constructor(public x: number, public y: number, public z?: number) {}
}
type PointParams = ConstructorParameters<typeof Point>;
// [number, number, number?]
let args: PointParams = [1, 2];
let point = new Point(...args);
(4) InstanceType—Get the constructor instance type
TYPESCRIPT
class Session {
constructor(public token: string) {}
isValid(): boolean { return this.token.length > 0; }
}
type SessionInstance = InstanceType<typeof Session>;
// Equivalent to Session Type
let session: SessionInstance = new Session("abc123");
5. Record—Building a Key-Value Pair Type
Record is one of the most commonly used data types—a type for quickly creating "key-value" mappings:
TYPESCRIPT
// Basic Usage:Key and Value Types
type StringMap = Record<string, string>;
let translations: StringMap = {
hello: "Hello",
goodbye: "Goodbye"
};
// Coordinated Literal-Union Types——Precision Control Key
type Theme = "light" | "dark";
type ThemeColors = Record<Theme, { bg: string; text: string }>;
let themes: ThemeColors = {
light: { bg: "#ffffff", text: "#333333" },
dark: { bg: "#1a1a1a", text: "#e0e0e0" }
};
// Abbreviation: Use Record instead of handwritten Object Types
type Scores = Record<"Chinese Language" | "Mathematics" | "English", number>;
let myScores: Scores = { Chinese Language: 90, Mathematics: 95, English: 88 };
6. How Tool Types Work
Understanding the underlying implementation of tool types helps with customizing them:
(1) Implementation of Partial
TYPESCRIPT
type Partial<T> = {
[K in keyof T]?: T[K];
};
keyof T—— The union type of all property keys of T[K in keyof T]— Iterate through each property key (mapped type)?— Add an optional modifierT[K]— Preserves the original attribute value type
(2) Implementation of Readonly
TYPESCRIPT
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
(3) Implementation of Pick
TYPESCRIPT
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
(4) Implementation of Omit
TYPESCRIPT
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
(5) Implementation of Record
TYPESCRIPT
type Record<K extends keyof any, T> = {
[P in K]: T;
};
▶ Example: Custom Tool Types
TYPESCRIPT
// DeepPartial——Recursion makes all levels optional
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
interface Config {
server: {
host: string;
port: number;
};
database: {
url: string;
pool: {
min: number;
max: number;
};
};
}
type PartialConfig = DeepPartial<Config>;
// Properties at all levels are now optional
let config: PartialConfig = {
server: { host: "localhost" } // port Can be omitted
// database The entire section can be omitted.
};
// DeepReadonly——Recursively set all levels to read-only
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
type FrozenConfig = DeepReadonly<Config>;
// config.server.host = "other"; // ❌ Deep Read-Only
Output:
TEXT
📖 Display only
No runtime output — demonstrates DeepPartial and DeepReadonly type utilities
❓ FAQ
Q What is the difference between
Partial and optional properties?A Optional properties are manually marked with
? when defining an interface. Partial is a tool type—it automatically makes all properties of an existing type optional. The difference is that Partial is "derived from an existing type" and does not require redefining the interface. In actual development, the UpdateUser = Partial<User> update operation is the most common use case.Q Should I use
Pick or Omit?A It depends on which is more concise—use
Pick when there are fewer properties to keep, and use Omit when there are fewer properties to exclude. The two are complementary; choose the shorter one. Code readability is key—Omit<User, "password"> is much clearer than Pick<User, "id" | "name" | "email" | "role">.Q Can
ReturnType determine the return type of an asynchronous function?A Asynchronous functions return a Promise;
ReturnType<typeof asyncFn> returns Promise<T> rather than T. You need to unwrap the Promise using Awaited<ReturnType<typeof asyncFn>> (TypeScript 4.5+ includes the Awaited type).Q Does the tool type affect performance?
A No. The tool type is purely a compile-time construct—all type information is erased after compilation, resulting in zero runtime overhead. However, overly complex type nesting may increase compilation time, though the actual impact is negligible.
📖 Summary
- Partial/Required/Readonly: The optionality and read-only nature of transformation attributes
- Pick/Omit: Select or exclude a specified attribute—choose the more concise option
- Record: Quickly create key-value pair types and precisely control keys in conjunction with literal union types
- Exclude/Extract/NonNullable operations on members of composite types
- ReturnType/Parameters/ConstructorParameters: Extracts type information about a function
- Tool types are based on map types +
keyof—once you understand how they work, you can create your own tool types
📝 Exercises
- Basic Exercise (Difficulty ⭐): Define the
Todointerface (id, title, completed, createdAt), then use the tool type to create:CreateTodo(id and time are not required when creating),UpdateTodo(all fields are optional when updating), andTodoPreview(only displays title and completed). - Advanced Exercise (Difficulty ⭐⭐): Customize the
Mutable<T>tool type—remove allreadonlymodifiers (using the-readonlymodifier mapping). Then useReadonly<Config>to create a read-only configuration, and useMutable<Readonly<Config>>to verify that writability has been restored. - Challenge (Difficulty: ⭐⭐⭐): Implement the
PathKeys<T>tool type—recursively extract all property paths of nested objects. For example,{ user: { name: string; address: { city: string } } }→"user" | "user.name" | "user.address" | "user.address.city".