TypeScript中判别器非特定时,可辨识联合类型收窄为何反常?
TypeScript 联合类型判别器的类型收窄异常解析
先看我们定义的枚举与类结构:
enum TaskType { WithId = 'WithId', WithValues = 'WithValues', WithNothing = 'WithNothing', } class TaskWithId { type: TaskType; // 此处为整个枚举类型,而非具体枚举值 id: number; } class TaskWithValues { type: TaskType.WithValues; // 指定具体枚举值 values: number[]; } class TaskWithNothing { type: TaskType.WithNothing; // 指定具体枚举值 } export type Task = TaskWithId | TaskWithValues | TaskWithNothing;
接下来看两个不符合直觉的类型收窄现象:
现象1:TaskWithId 能被正确类型收窄
用switch匹配TaskType.WithId时,TypeScript能准确推断当前task为TaskWithId类型:
switch (task.type) { case TaskType.WithId: const id = task.id; // 此处task被正确推断为TaskWithId break; }
原因
TaskWithValues和TaskWithNothing的type属性是固定的具体枚举值,它们的type不可能等于TaskType.WithId。只有TaskWithId的type是整个TaskType枚举,包含WithId这个值。所以当匹配到WithId时,TypeScript可以确定当前task只能是TaskWithId。
现象2:TaskWithValues 无法正确类型收窄
但匹配TaskType.WithValues时,TypeScript无法排除TaskWithId的可能性,导致task类型仍包含TaskWithId:
switch (task.type) { case TaskType.WithValues: // const values = task.values; // 报错:TaskWithId不存在values属性 break; }
原因
TaskWithId的type是整个TaskType枚举,这意味着它的type可以是枚举中的任意值,包括TaskType.WithValues。所以当匹配到WithValues时,TypeScript无法确定当前task到底是TaskWithValues还是TaskWithId(因为TaskWithId的type也可能等于WithValues),因此无法完成类型收窄。
内容的提问来源于stack exchange,提问作者wlf
相关产品推荐
相关产品推荐

