如何窄化区分联合类型?从联合类型提取指定成员类型
区分联合类型的窄化/提取方法
要从TypeScript的区分联合类型里提取符合特定条件的成员,最直接的方式有两种:自定义条件类型,或者用官方内置的Extract工具类型。
方法一:自定义条件类型实现
利用TypeScript的条件类型分发特性,可以自己写一个类型工具来筛选联合成员:
// 自定义类型工具:从Union中提取符合Filter条件的成员 type NarrowUnion<Union, Filter> = Union extends Filter ? Union : never; // 测试示例 type MyUnion = { kind: "foo", foo: number } | { kind: "bar", bar: string }; type Narrowed = NarrowUnion<MyUnion, { kind: "bar" }>; // Narrowed的结果就是 { kind: "bar", bar: string }
原理很简单:联合类型在条件类型中会自动拆分成单个成员逐一判断,每个成员如果能分配给Filter类型(也就是结构上包含Filter的属性),就保留该成员,否则返回never(never在联合类型中会被自动忽略)。
方法二:用内置的Extract工具类型
TypeScript已经内置了Extract<Union, Type>工具类型,专门用来从联合类型中提取可分配给Type的成员,功能和上面的NarrowUnion完全一致,不用重复造轮子:
type MyUnion = { kind: "foo", foo: number } | { kind: "bar", bar: string }; // 直接用Extract提取符合{ kind: "bar" }的类型 type Narrowed = Extract<MyUnion, { kind: "bar" }>;
如果需要筛选多个条件,也可以给第二个参数传联合类型:
type MyUnion = { kind: "foo", foo: number } | { kind: "bar", bar: string } | { kind: "baz", baz: boolean }; // 提取kind为"bar"或"baz"的成员 type MultiNarrowed = Extract<MyUnion, { kind: "bar" } | { kind: "baz" }>; // MultiNarrowed结果:{ kind: "bar", bar: string } | { kind: "baz", baz: boolean }
内容的提问来源于stack exchange,提问作者Qtax
相关产品推荐
相关产品推荐

