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

组件解构时Discriminating Union出现类型错误求助

解决联合类型组件解构时的TS属性不存在错误

你定义的IInfoBoxProps是WithAction和WithoutAction的联合类型,直接解构时TS会报错,核心原因是:customActionComponent、actionComponentPosition、actionBtnText、clickHandler这些属性仅存在于WithAction接口中,WithoutAction里完全没有,TS无法确定这些属性一定存在;另外你给isActionBtnRequired设置默认值true也不合理——联合类型里这个字段是明确的true或false,并非可选属性。

解决思路与步骤

  • 用isActionBtnRequired做类型守卫,自动区分两种类型的props
  • 仅在对应分支中访问专属属性,避免跨分支访问不存在的字段
  • 将默认值设置在对应分支内,遵循TS的类型检查规则

修改后的完整代码

import * as React from "react";
import { ReactNode } from "react";
import "./styles.css";

interface WithAction {
  isActionBtnRequired: true;
  content: string;
  containerClass?: string;
  customActionComponent?: ReactNode;
  actionComponentPosition?: ActionComponentPosition;
  actionBtnText?: string;
  clickHandler?: () => void;
}

interface WithoutAction {
  isActionBtnRequired: false;
  content: string;
  containerClass?: string;
}

type IInfoBoxProps = WithAction | WithoutAction;

type ActionComponentPosition = "floating-right" | "next-to-content";

export const App = (props: IInfoBoxProps) => {
  // 先解构所有分支共有的属性
  const { containerClass = "", content, isActionBtnRequired } = props;

  // 类型守卫:处理需要操作组件的情况
  if (isActionBtnRequired) {
    // TS自动收窄props为WithAction类型,可安全解构专属属性
    const {
      customActionComponent = null,
      actionComponentPosition = "floating-right",
      actionBtnText = "",
      clickHandler
    } = props;

    const renderActionBtn = (): ReactNode =>
      customActionComponent ? customActionComponent : (
        <button onClick={clickHandler} className="info-box-action-button">
          {actionBtnText}
        </button>
      );

    return (
      <div className={`info-box-container ${containerClass}`}>
        <div className="info-box-section">
          <span className="info-box-icon">icon</span>
          <div
            className={`${
              actionComponentPosition === "floating-right"
                ? "info-box-text-stretch"
                : "info-box-text"
            }`}
          >
            <span>{content}</span>
          </div>
          {renderActionBtn()}
        </div>
      </div>
    );
  } else {
    // 处理不需要操作组件的情况
    return (
      <div className={`info-box-container ${containerClass}`}>
        <div className="info-box-section">
          <span className="info-box-icon">icon</span>
          <div className="info-box-text">
            <span>{content}</span>
          </div>
        </div>
      </div>
    );
  }
};

关键细节说明

  1. 类型守卫的作用:当判断isActionBtnRequired === true时,TS会自动将props的类型收窄为WithAction,此时解构该接口的专属属性不会触发类型错误。
  2. 分支化渲染:将两种场景的渲染逻辑拆分,既符合TS的类型规则,也让代码逻辑更清晰。
  3. 默认值的合理放置:仅在WithAction分支内设置该类型专属属性的默认值,避免全局解构时访问不存在的字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:20:22