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];
};

(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
▶ Try it Yourself

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&lt;User&gt; 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

📝 Exercises

  1. Basic Exercise (Difficulty ⭐): Define the Todo interface (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), and TodoPreview (only displays title and completed).
  2. Advanced Exercise (Difficulty ⭐⭐): Customize the Mutable<T> tool type—remove all readonly modifiers (using the -readonly modifier mapping). Then use Readonly<Config> to create a read-only configuration, and use Mutable<Readonly<Config>> to verify that writability has been restored.
  3. 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".
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏