TypeScript 类型体操实用指南:从 Pick 到条件类型
Practical TypeScript Type Gymnastics: From Pick to Conditional Types
| Lisa | 2026-08-27T09:12:26
TypeScript 的类型系统强大但也容易让人头大。这篇文章不搞那些面试八股,聊聊实际开发中最常用的类型技巧。
TypeScript's type system is powerful but can be overwhelming. This article covers the most practical type techniques used in real development.
TypeScript 的类型体操文章网上一搜一大把,但大多数都是面试题级别的,实际开发中基本用不到。这篇文章聊聊我日常开发中真正高频使用的类型技巧。 1. 从 API 响应中提取类型 这是最常见的场景。后端返回的数据结构经常嵌套很深,手动定义类型太麻烦: // 假设这是 API 响应类型 interface ApiResponse { code: number; data: { list: Array<{ id: number; name: string; tags: string[]; meta: { createdAt: string; updatedAt: string }; }>; total: number; }; } // 提取 list 中单个 item 的类型 type ListItem = ApiResponse['data']['list'][number]; // { id: number; name: string; tags: string[]; meta: {...} } // 提取 meta 的类型 type ItemMeta = ListItem['meta']; // { createdAt: string; updatedAt: string } 2. 让部分字段可选 // 只让 id 和 createdAt 可选,其他必填 type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; // 创建用户时 id 是自动生成的 type CreateUserDTO = PartialBy<User, 'id' | 'createdAt'>; 3. 从常量数组推导联合类型 const STATUS = ['draft', 'published', 'archived'] as const; type Status = typeof STATUS[number]; // 'draft' | 'published' | 'archived' // 这样改数组就自动同步类型了,不用维护两份 4. 条件类型的实际用途 // 根据传入参数类型决定返回类型 function fetchData<T extends 'user' | 'order'>( type: T ): T extends 'user' ? UserData : OrderData { // ... } const user = fetchData('user'); // UserData const order = fetchData('order'); // OrderData 5. 模板字面量类型 type EventName = 'click' | 'hover' | 'focus'; type HandlerName = \`on\${Capitalize<EventName>}\`; // 'onClick' | 'onHover' | 'onFocus' // 自动生成事件处理器类型 type EventHandlers = { [K in HandlerName]: (event: Event) => void; }; 最后 类型体操适可而止就好。如果一个类型定义需要翻来覆去看好几遍才能理解,那可能是过度设计了。记住类型系统是工具不是目的,能让 IDE 正确提示、编译时发现错误就够了。
Most TypeScript type gymnastics articles focus on interview puzzles. Here are the actually useful patterns in daily development. Key Patterns Extract nested types from API responses using indexed access types PartialBy utility for making specific fields optional Derive union types from const arrays Conditional types for type-safe function overloads Template literal types for auto-generating handler names Keep type gymnastics pragmatic - if a type definition needs multiple reads to understand, it's probably over-engineered.