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

React TypeScript组件中如何实现Props的互斥条件类型约束?

解决Test组件Props的条件类型约束问题

需求说明

  • Test组件必须接收one prop,该对象必须包含a字段
  • 未提供two prop时,one必须包含id字段
  • 提供two prop时,one不能包含id字段

最初的无效尝试

以下接口无法实现one和two的条件关联:

interface Test {
  one: {
    a: string;
    id?: number;
  };
  two?: number;
}

演示代码

export default function App() {
  return (
    <div>
      <Test
        one={{
          a: 'valid example with id and no two prop',
          id: 5,
        }}
      />

      <Test
        one={{
          a: 'valid example with two prop and no id field',
        }}
        two={9}
      />

      <Test
        one={{
          a: 'should have id or two prop; needs to error',
        }}
      />

      <Test
        one={{
          a: 'cannot have both id field AND two prop; needs to error',
          id: 2,
        }}
        two={5}
      />
    </div>
  );
}

interface Test {
  one: {
    a: string;
    id?: number;
  };
  two?: number;
}

const Test = ({ one, two }: Test): JSX.Element => {
  return <p>test</p>;
};

错误的类型尝试

以下写法无法生效:

type One = {
  a: string
  id?: number
}

type Two = One.id ? number : null

更新的问题

之前的方案存在缺陷,会强制要求必须提供two prop,导致合法的组件实例报错。修改后的代码仍未解决问题:

interface A {
  a: string;
}
interface OptionOne {
  one: A & {
    id: number;
  };
  two: never;
}
interface OptionTwo {
  one: A;
  two: number;
}
type FinalType = OptionOne | OptionTwo;

const Test = ({ one, two }: FinalType): JSX.Element => {
  return <p>test</p>;
};

报错信息

Type '{ one: { a: string; }; }' is not assignable to type 'IntrinsicAttributes & FinalType'.
  Property 'two' is missing in type '{ one: { a: string; }; }' but required in type 'OptionTwo'

解决方案

通过调整联合类型的定义,让two在不需要时可省略,同时约束one的结构:

interface BaseOne {
  a: string;
}

type TestProps = 
  // 情况1:不传递two,one必须包含id
  {
    one: BaseOne & { id: number };
    two?: never;
  } 
  // 情况2:传递two,one不能包含id
  | {
    one: BaseOne & { id?: never };
    two: number;
  };

const Test = ({ one, two }: TestProps): JSX.Element => {
  return <p>test</p>;
};

说明

  • 第一个分支中,two?: never表示two可以不传递,此时TypeScript会匹配该分支,强制one必须包含id字段。
  • 第二个分支中,id?: never限制one不能有id字段(never类型无有效值),同时要求必须传递two。

该定义可完全满足需求:

  • 合法实例(带id无two、带two无id)可正常通过类型检查
  • 非法实例(无id无two、带id带two)会触发TypeScript错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 08:40:22