You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:05:03