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

React组件中API响应联合类型条件渲染的TypeScript报错问题

TypeScript联合类型条件渲染时报错的原因及解决方法

这是TypeScript类型窄化(Type Narrowing)机制的一个常见问题——你虽然提前判断了地址类型并把结果存在了布尔变量里,但TypeScript没办法追踪这些变量和原对象类型之间的关联,所以在条件分支里,它依然把props.deliveryAddress当成DeliveryAddress联合类型处理,自然会报错说某些属性在另一种类型里不存在。

为什么当前写法不行?

当你把props.deliveryAddress.type === AddressType.postal的结果赋值给isPostalAddress变量后,TypeScript丢失了这个变量和原对象类型的绑定关系。它只知道isPostalAddress是个布尔值,但没办法确定:当isPostalAddress为true时,props.deliveryAddress一定是PostalAddress类型。所以在{isPostalAddress && ...}的分支里,TypeScript依然会认为props.deliveryAddress可能是PackstationAddress,从而报错。

解决方案

这里有几种可靠的解决方式,你可以根据自己的习惯选择:

1. 直接在条件判断中使用类型检查(最直接)

把类型判断逻辑直接写在JSX的条件里,这样TypeScript能直接识别到类型窄化:

const DeliveryAddressDisplay = (props: Props) => {
  return (
    <div className="App">
      {props.deliveryAddress.type === AddressType.postal && (
        <>
          <h2>Street: {props.deliveryAddress.street}</h2>
          <h2>Street Number: {props.deliveryAddress.streetNumber}</h2>
        </>
      )}
      {props.deliveryAddress.type === AddressType.packstation && (
        <>
          <h2>Packstation: {props.deliveryAddress.packstation}</h2>
          <h2>Post Number: {props.deliveryAddress.postNumber}</h2>
        </>
      )}
    </div>
  );
};

2. 使用自定义类型守卫函数

如果希望把类型判断逻辑抽离出来,可以写一个类型守卫函数,明确告诉TypeScript判断后的类型:

// 在types.ts里添加类型守卫
export function isPostalAddress(address: DeliveryAddress): address is PostalAddress {
  return address.type === AddressType.postal;
}

export function isPackstationAddress(address: DeliveryAddress): address is PackstationAddress {
  return address.type === AddressType.packstation;
}

然后在组件里使用:

const DeliveryAddressDisplay = (props: Props) => {
  const address = props.deliveryAddress;
  
  return (
    <div className="App">
      {isPostalAddress(address) && (
        <>
          <h2>Street: {address.street}</h2>
          <h2>Street Number: {address.streetNumber}</h2>
        </>
      )}
      {isPackstationAddress(address) && (
        <>
          <h2>Packstation: {address.packstation}</h2>
          <h2>Post Number: {address.postNumber}</h2>
        </>
      )}
    </div>
  );
};

3. 使用switch语句(更适合复杂场景)

switch语句的case分支能让TypeScript自动做类型窄化,代码结构也更清晰:

const renderAddress = (address: DeliveryAddress) => {
  switch (address.type) {
    case AddressType.postal:
      return (
        <>
          <h2>Street: {address.street}</h2>
          <h2>Street Number: {address.streetNumber}</h2>
        </>
      );
    case AddressType.packstation:
      return (
        <>
          <h2>Packstation: {address.packstation}</h2>
          <h2>Post Number: {address.postNumber}</h2>
        </>
      );
  }
};

const DeliveryAddressDisplay = (props: Props) => {
  return (
    <div className="App">
      {renderAddress(props.deliveryAddress)}
    </div>
  );
};

这些方法都能让TypeScript正确识别条件分支里的具体类型,解决报错问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:02:30