如何在React组件中用TypeScript函数重载实现条件必填Props?
实现React组件条件必填属性的方案
你提到的需求可以通过TypeScript可辨识联合类型或函数重载两种方式实现,具体操作如下:
方案1:可辨识联合类型(更推荐)
这是TypeScript针对条件类型场景的原生解决方案,比函数重载更简洁易维护,逻辑是将两种场景的Props拆成联合类型:
isBoy为true时,强制要求携带actionHero和nicknameisBoy为false/不传时,不允许使用这两个属性
代码实现
// 提取两种场景通用的公共属性 interface CommonProps { color: string name?: string height?: number } // 男孩场景专属属性 interface BoyProps extends CommonProps { isBoy: true actionHero: string nickname: string } // 非男孩场景属性 interface NonBoyProps extends CommonProps { isBoy?: false actionHero?: never nickname?: never } // 最终的Props联合类型 type MyProps = BoyProps | NonBoyProps // 组件代码 function MyComponent(props: MyProps) { // 类型收窄:判断isBoy后可以安全访问专属属性,不会报类型错误 if (props.isBoy) { console.log(props.actionHero, props.nickname) } return <div style={{ color: props.color }}>{props.name}</div> }
方案2:函数重载实现
如果你更倾向用函数重载的方式,也可以通过定义多组函数签名实现同样的校验效果:
// 重载签名1:传入isBoy={true}时,必须携带两个必填属性 function MyComponent(props: { color: string name?: string height?: number isBoy: true actionHero: string nickname: string }): JSX.Element // 重载签名2:传入isBoy={false}时,不需要两个属性 function MyComponent(props: { color: string name?: string height?: number isBoy?: false actionHero?: never nickname?: never }): JSX.Element // 重载签名3:不传isBoy时,不需要两个属性 function MyComponent(props: { color: string name?: string height?: number actionHero?: never nickname?: never }): JSX.Element // 实现签名,类型需要兼容所有重载场景 function MyComponent(props: any) { if (props.isBoy) { console.log(props.actionHero, props.nickname) } return <div style={{ color: props.color }}>{props.name}</div> }
校验效果验证
两种方案都可以实现预期的类型校验:
- 合法调用不会报错:
<MyComponent color="red" /> <MyComponent color="blue" isBoy={false} name="小红" /> <MyComponent color="green" isBoy={true} actionHero="蜘蛛侠" nickname="明明" /> - 非法调用会触发TypeScript错误:
// 报错:isBoy为true时缺少actionHero和nickname <MyComponent color="red" isBoy={true} /> // 报错:非男孩场景不允许传递actionHero属性 <MyComponent color="red" actionHero="蝙蝠侠" />
内容的提问来源于stack exchange,提问作者user10741122
相关产品推荐
相关产品推荐

