如何在TypeScript中对两个联合类型变量进行类型收窄?
解决方案
问题核心
虽然代码里已经通过 a.type !== b.type 排除了类型不匹配的情况,但 TypeScript 无法自动将 b 的类型同步收窄为与 a 一致的类型,导致访问专属属性时报错。以下是几种简洁的实现方式,无需额外增加9次类型检查:
方案一:类型断言(最简洁)
由于已经确保 a.type === b.type,可以安全地将 b 断言为对应类型:
interface A { type: "A"; propsOfA: string; } interface B { type: "B"; propsOfB: number; } interface C { type: "C"; propsOfC: boolean; } function isEqual(a: A | B | C, b: A | B | C) { if (a.type !== b.type) { return false; } switch (a.type) { case "A": { return a.propsOfA === (b as A).propsOfA; } case "B": { return a.propsOfB === (b as B).propsOfB; } case "C": { return a.propsOfC === (b as C).propsOfC; } } }
方案二:自定义类型守卫
创建通用类型守卫函数,同时收窄 a 和 b 的类型:
interface A { type: "A"; propsOfA: string; } interface B { type: "B"; propsOfB: number; } interface C { type: "C"; propsOfC: boolean; } type UnionType = A | B | C; // 通用类型守卫,根据type字段收窄类型 function isType<T extends UnionType["type"]>(obj: UnionType, type: T): obj is Extract<UnionType, { type: T }> { return obj.type === type; } function isEqual(a: UnionType, b: UnionType) { if (a.type !== b.type) { return false; } if (isType(a, "A") && isType(b, "A")) { return a.propsOfA === b.propsOfA; } if (isType(a, "B") && isType(b, "B")) { return a.propsOfB === b.propsOfB; } if (isType(a, "C") && isType(b, "C")) { return a.propsOfC === b.propsOfC; } return false; }
方案三:泛型+映射类型(适合扩展更多类型)
通过泛型重载和属性提取,实现通用的类型匹配与属性比较:
interface A { type: "A"; propsOfA: string; } interface B { type: "B"; propsOfB: number; } interface C { type: "C"; propsOfC: boolean; } type UnionType = A | B | C; // 重载函数签名,支持精确类型匹配 function isEqual<T extends UnionType["type"]>(a: Extract<UnionType, { type: T }>, b: Extract<UnionType, { type: T }>): boolean; function isEqual(a: UnionType, b: UnionType): boolean; function isEqual(a: UnionType, b: UnionType): boolean { if (a.type !== b.type) { return false; } // 提取并比较除type外的属性(支持多属性扩展) const [aProp] = Object.values(a).filter(val => val !== a.type); const [bProp] = Object.values(b).filter(val => val !== b.type); return aProp === bProp; }
内容的提问来源于stack exchange,提问作者Darkproduct
相关产品推荐
相关产品推荐

