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

React TypeScript条件Props传参时类型不匹配报错如何解决

问题描述

我正在开发一个接收inside和position两个props的组件,规则如下:

  • 当inside值为true时,position仅支持left、bottom两个取值
  • 当inside值为false时,position支持left、bottom、right、top四个取值

初始实现代码如下:

type InsidePosition = "bottom" | "left"
type OutsidePosition = "top" | "right" | InsidePosition

type CoordinatesProps =
  | { inside: true, position: InsidePosition}
  | { inside: false, position: OutsidePosition}


function Coordinates({ position, inside } : CoordinatesProps) {
  const CoordinateComponent = inside ? InsideCoordinate : OutsideCoordinate;

  return _.times(8, (index: number) => {
    return <CoordinateComponent
      key={ `${ position }-${ index }` }
      index={ index }
      position={ position }
    />;
  });
}

子组件InsideCoordinate和OutsideCoordinate的定义如下:

type InsideCoordinateProps = {
  position: InsidePosition,
  index: number,
};

function InsideCoordinate({ position, index }: InsideCoordinateProps) {
  // 组件业务逻辑
}

type OutsideCoordinateProps = {
  position: OutsidePosition,
  index: number,
};

function OutsideCoordinate({ position, index }: OutsideCoordinateProps) {
  // 组件业务逻辑
}

报错信息

给CoordinateComponent传递position={ position }属性时,触发TypeScript类型报错:

typescript: Type '"bottom" | "left" | "top" | "right"' is not assignable to type '"bottom" | "left"'.
  Type '"top"' is not assignable to type '"bottom" | "left"'. [2322]

问题原因

你的联合类型定义本身没有错误,报错核心是TypeScript不会跟踪三元表达式赋值的变量和原解构变量之间的类型关联。
当执行const CoordinateComponent = inside ? InsideCoordinate : OutsideCoordinate时,TS只会将该变量推导为两个组件类型的联合:typeof InsideCoordinate | typeof OutsideCoordinate,同时该作用域下position的类型是四个取值的全量联合。TS不支持跨变量的类型关联收窄,不会自动识别「选中InsideCoordinate时position必然是InsidePosition、选中OutsideCoordinate时position必然是OutsidePosition」的对应关系,校验props时会检查所有可能的组件是否能接收所有可能的position值,自然会抛出top/right无法传给InsideCoordinate的错误。


正确解决方式

不需要使用类型断言,有两种类型安全的实现方案:

方案1:在分支内直接渲染对应组件(推荐)

放弃中间组件变量,把判断逻辑放到JSX分支中,TS可以在同一个代码块内自动完成类型收窄:

function Coordinates({ position, inside } : CoordinatesProps) {
  return _.times(8, (index: number) => {
    return inside ? (
      <InsideCoordinate
        key={`${position}-${index}`}
        index={index}
        position={position}
      />
    ) : (
      <OutsideCoordinate
        key={`${position}-${index}`}
        index={index}
        position={position}
      />
    )
  });
}

这种写法下,inside为true的分支内TS会自动收窄position类型为InsidePosition,完全匹配子组件的props要求,不会触发类型报错。

方案2:提前收窄类型再赋值组件变量

如果确实需要抽离组件变量,可以先通过判别式收窄props类型,再给变量赋值:

function Coordinates(props : CoordinatesProps) {
  let CoordinateComponent: typeof InsideCoordinate | typeof OutsideCoordinate;
  let position: InsidePosition | OutsidePosition;

  if (props.inside) {
    CoordinateComponent = InsideCoordinate;
    position = props.position; // 此处TS自动识别position为InsidePosition类型
  } else {
    CoordinateComponent = OutsideCoordinate;
    position = props.position; // 此处TS自动识别position为OutsidePosition类型
  }

  return _.times(8, (index) => {
    return <CoordinateComponent
      key={ `${ position }-${ index }` }
      index={ index }
      position={ position }
    />;
  });
}

该写法冗余度更高,日常开发优先选择第一种方案即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:54:21