React TS组件封装:优雅混合自定义与原生Props的方案问询
解决React扩展原生组件时的Props分离问题
问题背景
封装input、button、table等原生元素的扩展组件时,手动添加团队所需的事件处理器和Props过于繁琐。曾尝试让组件Prop类型继承原生Prop类型并自动展开,但出现自定义Props不被类型支持、自定义Props意外传递给原生元素的问题。当前采用的方案需要重复定义所有自定义Prop名称才能分离原生Props,还失去了习惯的props.前缀来区分Props与局部变量。
可行的简洁解决方案
方案1:通用工具函数分离Props
编写一个可复用的工具函数,根据自定义Props的键名,自动将传入的Props拆分为自定义部分和原生部分,既不用重复解构自定义Prop,也能保留类props.的前缀:
import React from 'react'; // 通用Props分离函数,支持所有组件复用 const splitProps = <T, U extends keyof T>(props: T, customKeys: U[]) => { const customProps: Pick<T, U> = {} as Pick<T, U>; const nativeProps: Omit<T, U> = {} as Omit<T, U>; Object.keys(props).forEach(key => { if (customKeys.includes(key as U)) { (customProps as any)[key] = props[key]; } else { (nativeProps as any)[key] = props[key]; } }); return { customProps, nativeProps }; }; // 自定义Props类型 type CustomProps = { color: string; label: React.ReactNode; }; // 组合类型:自定义Props + 排除重名后的原生button Props type Props = CustomProps & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof CustomProps>; const Button = (props: Props) => { // 传入自定义键名数组,一键分离 const { customProps, nativeProps } = splitProps(props, ['color', 'label']); return ( <> {customProps.label} <button {...nativeProps} style={{ backgroundColor: customProps.color, ...nativeProps.style }} /> </> ); }; export default Button;
方案2:类型断言+剩余属性(极简写法)
如果不想额外写工具函数,可以结合TypeScript类型断言,仅解构一次自定义键名,同时保留完整props对象用于访问自定义属性:
import React from 'react'; type CustomProps = { color: string; label: React.ReactNode; }; type Props = CustomProps & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof CustomProps>; const Button = (props: Props) => { // 解构出自定义键名,剩余属性自动匹配原生Props类型 const { color, label, ...nativeProps } = props; // 依然可以通过props.前缀访问自定义属性,避免和局部变量混淆 return ( <> {props.label} <button {...nativeProps} style={{ backgroundColor: props.color, ...nativeProps.style }} /> </> ); }; export default Button;
注意事项
你之前期望的示例写法不符合React组件规范:React组件仅能接收单个props对象参数,无法拆分为两个独立参数分别接收自定义和原生Props,因此该写法无法正常运行。
内容的提问来源于stack exchange,提问作者MFischer
相关产品推荐
相关产品推荐

