TypeScript 2.8条件类型报错:Type A无法赋值给Type B及相关问题跟进
增强TypeScript 2.8中的Partition类型
刚好在TypeScript 2.8的条件类型特性上踩过类似的坑,我来给你捋清楚怎么实现增强版的partition类型,结合你给出的Option和Seq示例来拆解。
首先,先明确核心需求:partition的本质是把一个联合类型拆成满足指定条件和不满足指定条件的两个子集。TypeScript 2.8新增的Exclude是基础,但我们可以把它封装成更易用的结构类型。
1. 通用Partition类型定义
先搞一个通用版的,支持自定义判断条件:
type Partition<T, Condition> = { // 匹配条件的类型子集:利用分布式条件类型遍历联合成员 matches: T extends Condition ? T : never; // 不匹配的子集:用Exclude剔除匹配项 nonMatches: Exclude<T, Condition>; };
这里用到了TypeScript 2.8的分布式条件类型——当T是联合类型时,T extends Condition ? ...会自动逐个检查每个联合成员,完美适配我们拆分联合类型的需求。
2. 针对你的Option/Seq场景定制
结合你给出的Option<T>和Seq<T>,比如你想把一个包含Option、Seq和其他类型的联合类型拆分,只提取Option相关的类型:
// 先定义你的基础类型(和你给出的一致) export class Option<T> { toVector(): Vector<T> { return <any>undefined; } } interface Seq<T> { tail(): Option<Seq<T>>; // 假设还有其他方法... } interface Vector<T> {} // 测试用的联合类型 type MixedTypes = Seq<number> | Option<string> | number | Option<boolean>; // 用通用Partition拆分出Option类型和其他类型 type PartitionedOptions = Partition<MixedTypes, Option<any>>;
最终PartitionedOptions的类型会是:
{ matches: Option<string> | Option<boolean>; nonMatches: Seq<number> | number; }
3. 进阶:函数中的类型安全Partition
如果要在Seq的操作函数中实现类型安全的partition方法,可以结合类型谓词来做:
declare function partitionSeq<T, U extends T>( seq: Seq<T>, predicate: (item: T) => item is U ): [Seq<U>, Seq<Exclude<T, U>>];
这样调用时,TypeScript会自动推断出拆分后的两个Seq的具体类型,完全符合类型安全要求。
避坑提示
- 如果你不想让条件类型“分布式”(比如处理非联合类型时),可以用元组包裹类型来避免:
[T] extends [Condition] ? T : never - 确保你用的是TypeScript 2.8 RC及以上版本,并且
tsconfig.json中开启了strictNullChecks(很多条件类型的行为依赖这个选项) Exclude<T, U>的本质是“剔除T中可分配给U的类型”,所以Exclude<T, Exclude<T, U>>其实等价于T extends U ? T : never,也就是我们的matches部分,两种写法都可以。
内容的提问来源于stack exchange,提问作者Emmanuel Touzery
相关产品推荐
相关产品推荐

