如何为React.Children.map添加未暴露给消费者的内部props并正确声明TS类型?
解决方案
核心思路是拆分Inner组件的属性为「外部传入的公开属性」和「Wrapper注入的私有属性」,对外仅暴露包含公开属性的组件类型,内部通过安全类型断言获取注入属性,完全不会将内部属性暴露给使用者。
步骤1:拆分属性类型
// Inner 对外公开的属性,使用者仅需传入该部分内容 interface InnerPublicProps { title: string; caption: string; } // Inner 内部使用的注入属性,由Wrapper自动传递,完全不对外暴露 interface InnerInjectedProps { onChange: (e: React.SyntheticEvent) => void; value: number | null; selected: boolean; } // Inner 内部实际用到的完整属性类型 type InnerFullProps = InnerPublicProps & InnerInjectedProps;
步骤2:调整Inner组件声明
对外导出的Inner组件类型仅声明公开属性,内部通过类型断言获取注入属性:
// 对外暴露的组件类型仅要求传入公开属性 export const Inner: React.FC<InnerPublicProps> = (props) => { // 内部断言为完整属性类型,该操作是安全的:只有被Wrapper包裹的Inner才会被渲染,Wrapper保证注入全部私有属性 const { title, caption, onChange, value, selected } = props as unknown as InnerFullProps; return ( <ThirdPartyComponent onChange={onChange} value={value} selected={selected}> <h1>{title}</h1> <h5>{caption}</h5> </ThirdPartyComponent> ); };
步骤3:(可选)优化Wrapper类型,替换any
const Wrapper: React.FC<{ value: number | null; handleChange: (index: number) => (e: React.SyntheticEvent, newValue: number | null) => void; }> = ({ value, handleChange, children }) => { return React.Children.map(children, (child, index) => { if (!child || !React.isValidElement(child)) { return null; } return React.cloneElement(child, { onChange: handleChange(index), value, selected: value === index, ...child.props, }); }); };
调整后,使用者调用<Inner />时,TS只会提示需要传入title和caption两个属性,onChange、value、selected三个内部属性完全不会对外暴露,也不需要设置为可选属性,完全符合要求。
内容的提问来源于stack exchange,提问作者alexunder
相关产品推荐
相关产品推荐

