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

如何强制JSX组件可选属性组需同时提供或都不提供?

实现JSX组件属性的关联约束(link与title必须同时存在或缺失)

我有一个<Icon/> JSX组件,它可选择接受link和title属性,但要求当其中一个被提供时,另一个也必须被提供。现有基础代码如下:

interface IconProps {
  width?: number
  height?: number
  alt?: string
  src: string
}

interface IconWithLink {
  link: string
  title: string
}

declare function BetterIcon({ height, width, src, alt, ...rest }: BetterIconProps): any

尝试过的无效方案

我尝试了多种组合及继承原接口的方式,但都无法实现预期约束:

type BetterIconProps = IconProps | (IconProps & IconWithLink)
type BetterIconProps = IconProps & (IconWithLink | {})

上述写法的问题是:智能提示会显示属性非可选,但实际未提供属性时不会触发TypeScript报错。

当前可行但扩展性差的方案

最终我通过以下方式实现了需求,但新增其他可选属性组时需要重复定义接口,扩展性差:

type BetterIconProps = IconWithoutLink | IconWithLink

interface IconProps {
  width?: number
  height?: number
  alt?: string
  src: string
}

interface IconWithoutLink extends IconProps {
  link?: never
  title?: never
}

interface IconWithLink extends IconProps {
  link: string
  title: string
}

是否有更通用、更简洁的实现方式?


更通用简洁的实现方式

可以通过封装通用关联属性工具类型来解决这个问题,避免重复定义多组接口,同时提升扩展性。

第一步:定义通用工具类型

这个工具类型的作用是:指定一组属性,要么同时传入(所有属性必填),要么同时不传(所有属性不能出现):

type LinkedProps<T> = T | { [K in keyof T]?: never };

第二步:组合最终的组件属性类型

基于原IconProps和需要关联的属性组,直接组合出BetterIconProps:

interface IconProps {
  width?: number;
  height?: number;
  alt?: string;
  src: string;
}

// 定义需要关联的属性对
interface LinkTitlePair {
  link: string;
  title: string;
}

// 组合得到最终属性类型
type BetterIconProps = IconProps & LinkedProps<LinkTitlePair>;

declare function BetterIcon(props: BetterIconProps): JSX.Element;

效果验证

  • 仅传入link或仅传入title:TypeScript会抛出类型错误
  • 同时传入link和title:类型校验通过
  • 两个属性都不传入:类型校验通过

扩展多组关联属性

如果后续需要新增其他关联属性组(比如target和rel必须同时存在或缺失),只需新增对应属性组并扩展BetterIconProps即可:

// 新增另一组关联属性
interface LinkTargetPair {
  target: string;
  rel: string;
}

// 扩展属性类型
type BetterIconProps = IconProps 
  & LinkedProps<LinkTitlePair> 
  & LinkedProps<LinkTargetPair>;

这种方式无需重复定义大量子接口,新增关联属性组的成本极低。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 10:57:33