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

如何在TypeScript中判断对象联合类型并实现类型窄化?

解决TypeScript联合类型推断失效的问题

问题原因

当前代码中,handleType函数返回CA | CB联合类型,但TypeScript无法根据输入的具体值自动缩小这个联合类型的范围,导致result.unionKey无法正确提示对应属性。此外,直接使用'keyOne' in obj.unionKey进行类型判断时,虽然TypeScript能在局部缩小obj.unionKey的类型,但封装到函数后,类型关联丢失。

解决方案

方案1:给handleType添加泛型条件返回类型

通过泛型将输入类型与返回类型关联,让TypeScript根据输入的具体值推断出精确的返回类型:

type A = {
  keyOne: string;
  keyTwo: string;
};

type B = {
  keyThree: string;
  keyFour: string;
};

type C = {
  unionKey: A | B;
  keyFive: string;
};

type CA = { unionKey: A; keyFive: string };
type CB = { unionKey: B; keyFive: string };

// 泛型函数,根据输入的unionKey类型返回对应类型
const handleType = <T extends C>(obj: T): T['unionKey'] extends A ? CA : CB => {
  if ('keyOne' in obj.unionKey) {
    return obj as CA;
  } else {
    return obj as CB;
  }
};

// 此时TypeScript会自动推断result为CB类型
const result = handleType({
  unionKey: { keyThree: 'sdfsd', keyFour: 'sadfasd' },
  keyFive: 'sdfsd',
});

result.unionKey.keyThree; // 自动提示生效
result.unionKey.keyFour; // 自动提示生效

方案2:使用类型守卫函数直接缩小类型

自定义类型守卫函数,在需要判断类型的地方直接使用,避免封装函数导致的类型关联丢失:

type A = {
  keyOne: string;
  keyTwo: string;
};

type B = {
  keyThree: string;
  keyFour: string;
};

type C = {
  unionKey: A | B;
  keyFive: string;
};

type CA = { unionKey: A; keyFive: string };
type CB = { unionKey: B; keyFive: string };

// 判断是否为CA类型的守卫函数
function isCA(obj: C): obj is CA {
  return 'keyOne' in obj.unionKey;
}

// 判断是否为CB类型的守卫函数
function isCB(obj: C): obj is CB {
  return 'keyThree' in obj.unionKey;
}

const obj: C = {
  unionKey: { keyThree: 'test', keyFour: 'test' },
  keyFive: 'test',
};

if (isCA(obj)) {
  obj.unionKey.keyOne; // 提示A的属性
} else {
  obj.unionKey.keyThree; // 提示B的属性
}

方案3:重构为可区分联合类型(推荐)

给A和B添加一个专门的区分属性(比如type),让TypeScript能更可靠地自动缩小类型范围,这是最健壮的解决方案:

type A = {
  type: 'A'; // 区分属性
  keyOne: string;
  keyTwo: string;
};

type B = {
  type: 'B'; // 区分属性
  keyThree: string;
  keyFour: string;
};

type C = {
  unionKey: A | B;
  keyFive: string;
};

const obj: C = {
  unionKey: { type: 'B', keyThree: 'test', keyFour: 'test' },
  keyFive: 'test',
};

// TypeScript自动将unionKey缩小为B类型
if (obj.unionKey.type === 'B') {
  obj.unionKey.keyThree; // 自动提示完美生效
}

内容的提问来源于stack exchange,提问作者amdev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 12:45:34