考察点分析

核心能力维度
本题考察对TypeScript类型系统高级特性的掌握程度,重点检验以下维度:

  1. 工具类型原理理解:能否准确解释Extract工具类型的工作机制
  2. 类型兼容性判断:对类型系统赋值兼容规则的掌握程度
  3. 联合类型操作:处理联合类型时的分布式条件类型特性
  4. 实际场景应用:将类型工具应用于具体业务场景的能力

技术评估点

  • 条件类型(Conditional Types)的分布式特性
  • 类型兼容性(Type Compatibility)规则
  • 工具类型的实现原理
  • 浏览器事件类型的类型体系认知

技术解析

关键知识点

  1. 条件类型分布式特性T extends U ? T : never
  2. 类型兼容性:结构化类型系统(Duck Typing)的赋值规则
  3. 工具类型实现Extract<T, U> 类型运算过程

原理剖析

当使用Extract<T, U>时:

  1. TypeScript会将联合类型T拆分为多个独立类型(分布式条件类型)
  2. 对每个子类型K进行判断:K是否可赋值给U
  3. 通过条件类型保留满足K extends U的子类型
  4. 最终合并所有满足条件的类型形成新联合类型
  // 伪代码实现
type Extract<T, U> = T extends U ? T : never
  

常见误区

  1. 误认为Extract<1|'a', number>结果为number类型(实际为1字面量类型)
  2. 混淆T extends UU extends T的方向判断
  3. 忽略never类型在联合类型中的自动过滤特性

问题解答

Extract工具类型通过条件类型的分布式特性,筛选出联合类型T中所有能赋值给类型U的成员。其本质是通过T extends U ? T : never类型运算,将联合类型拆分为独立类型进行兼容性判断,保留符合要求的类型。

场景演示

  // 定义浏览器事件类型联合
type EventTypes = 
  | MouseEvent 
  | KeyboardEvent
  | TouchEvent
  | FocusEvent;

// 提取鼠标相关事件类型
type MouseEvents = Extract<EventTypes, MouseEvent>;  // MouseEvent
  

解决方案

编码示例

  // 定义完整的浏览器事件类型体系
interface BaseEvent {
  readonly timeStamp: number
}

interface MouseEvent extends BaseEvent {
  x: number
  y: number
}

interface KeyboardEvent extends BaseEvent {
  key: string
}

// 联合类型包含多种事件
type AllEvents = MouseEvent | KeyboardEvent | Event;

// 类型提取:此处将正确提取出MouseEvent类型
type ExtractedMouseEvents = Extract<AllEvents, MouseEvent>;

// 测试用例
const handleMouseEvent = (e: ExtractedMouseEvents) => {
  console.log(`坐标:${e.x}, ${e.y}`)
};
  

优化说明

  1. 类型运算时间复杂度O(n),n为联合类型成员数量
  2. 通过接口继承保证类型结构兼容性
  3. 使用Extract替代手动过滤提升代码可维护性

深度追问

问题1:ExtractExclude的核心区别?

提示Exclude是取补集,Extract是取交集

问题2:如何提取所有包含特定属性的类型?

提示:使用条件类型T extends { prop: infer P } ? T : never

问题3:如何处理联合类型中的never

提示:联合类型会自动过滤never,如1 | never等价于1

Last updated 06 Mar 2025, 13:07 +0800 . history