如何优化React组件TypeScript类型,传入不存在label时触发类型错误
解决方案:通过泛型提取子元素label类型实现类型校验
要实现传入的label必须是子元素中存在的label值,核心是让组件的类型依赖于children的具体属性类型,通过泛型组件捕获子元素的label联合类型,具体修改如下:
完整修改代码
import React from 'react'; // 约束子元素必须包含label属性 type LabeledChild = React.ReactElement<{ label: string }>; // 泛型Props类型,T为子元素的具体类型 type CompProps<T extends LabeledChild> = { children: T[]; } & ( // 传入index时,label必须为never(互斥) | { index: number; label: never; } // 传入label时,只能是子元素label的联合类型,index为never | { label: T['props']['label']; index: never; } ); function Comp<T extends LabeledChild>(props: CompProps<T>) { // 实现根据index或label返回对应子元素的逻辑 let targetChild = null; if ('index' in props) { targetChild = props.children[props.index]; } else { targetChild = props.children.find(child => child.props.label === props.label); } return <div>{targetChild}</div>; } function Main() { return ( <Comp label="four"> {/* 此处会触发TypeScript错误:"four"不在允许的label列表中 */} <div label="One"> <p>One</p> </div> <div label="Two"> <p>Two</p> </div> <div label="Three"> <p>Three</p> </div> </Comp> ); } export default Main;
关键实现细节
泛型组件捕获子元素类型:
将Comp定义为泛型组件Comp<T extends LabeledChild>,TypeScript会自动推断出children中每个元素的具体类型,包括它们的label属性值(比如例子中的"One" | "Two" | "Three")。提取子元素label的联合类型:
通过T['props']['label']从子元素的props中提取label的类型,这样labelprop的类型就被限制为子元素已有的label值集合,传入不存在的label时会直接触发类型错误。保持props互斥性:
保留了原有的联合类型写法,确保index和label只能二选一传入,避免逻辑冲突。语法错误修正:
修复了原代码中的多余闭合标签、未闭合的<button>、错误的export语法等问题,确保代码可以正常运行。
内容的提问来源于stack exchange,提问作者Eve
相关产品推荐
相关产品推荐

