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

如何在React函数组件中正确使用TypeScript判别式联合?

React函数组件中TypeScript判别式联合的正确实现方式

你完全可以用原始的判别式联合定义来实现,不需要重复声明属性并设为null/never。核心是先通过判别式完成类型收窄,再在对应分支里解构属性,而不是一开始就解构所有可能的属性。

步骤示例

首先定义你的判别式联合Props类型:

type MyComponentProps =
  | { type: 'event'; startDate: Date; endDate: Date }
  | { type: 'task'; deadline: Date };

错误写法(导致IDE报错)

直接解构所有属性会让TypeScript无法收窄类型,因为它不知道当前type对应的具体分支:

// 错误:startDate可能不存在(当type为'task'时),会抛出TS2339
const MyComponent = ({ type, startDate }: MyComponentProps) => {
  return <div>{startDate}</div>;
};

正确写法1:先判断判别式,再分支内解构

先接收完整的props,通过判别式type做条件判断后,TypeScript会自动收窄当前分支的类型,此时再解构对应属性就不会报错:

const MyComponent = (props: MyComponentProps) => {
  if (props.type === 'event') {
    // 此处props已被收窄为event类型,可安全解构startDate/endDate
    const { startDate, endDate } = props;
    return (
      <div>
        活动:{startDate.toLocaleDateString()} 至 {endDate.toLocaleDateString()}
      </div>
    );
  } else {
    // 此处props被收窄为task类型,可安全解构deadline
    const { deadline } = props;
    return <div>任务:截止日期 {deadline.toLocaleDateString()}</div>;
  }
};

正确写法2:先解构判别式,再分支处理剩余属性

如果需要提前解构通用属性(比如所有分支都有的id、className),可以先解构判别式和通用属性,再在分支里处理剩余属性:

type MyComponentProps =
  | { type: 'event'; id: string; startDate: Date; endDate: Date }
  | { type: 'task'; id: string; deadline: Date };

const MyComponent = ({ id, type, ...rest }: MyComponentProps) => {
  // 通用属性id可直接使用
  if (type === 'event') {
    const { startDate, endDate } = rest;
    return (
      <div id={id}>
        活动:{startDate.toLocaleDateString()} 至 {endDate.toLocaleDateString()}
      </div>
    );
  } else {
    const { deadline } = rest;
    return <div id={id}>任务:截止日期 {deadline.toLocaleDateString()}</div>;
  }
};

原理说明

TypeScript的判别式联合类型收窄依赖条件判断语句,只有当你用判别式(比如这里的type字段)明确分支后,TypeScript才能确定当前分支对应的具体类型,此时解构对应属性就会被视为安全操作,不会抛出不存在的属性错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 19:13:18