React中如何阻止将className和style属性传递给自定义组件
React+TypeScript 自定义按钮排除className、style属性实现方案
核心思路
需要同时完成类型层面的属性限制和运行时的属性过滤两步,仅用Omit做类型声明无法完全禁止外部样式传入。
完整实现代码
首先定义组件类型,通过Omit移除原生按钮属性中的className和style,再显式将两个属性设为never避免类型合并时的遗漏:
import React, { ButtonHTMLAttributes, forwardRef } from 'react'; // 组件属性定义 type CustomButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'style'> & { // 你自己的自定义属性,示例如下 variant?: 'primary' | 'secondary' | 'text'; size?: 'small' | 'middle' | 'large'; // 显式禁止传入className、style,优先级高于其他合并来的类型 className?: never; style?: never; }; // 组件实现(支持ref透传) const CustomButton = forwardRef<HTMLButtonElement, CustomButtonProps>((props, ref) => { const { variant = 'primary', size = 'middle', // 运行时过滤掉禁止透传的属性,就算用户强制传入也不会生效 className: _ignoreClassName, style: _ignoreStyle, ...restNativeProps } = props; // 组件内部固定样式,外部无法修改 const internalClassName = `custom-btn custom-btn-${variant} custom-btn-${size}`; return ( <button ref={ref} className={internalClassName} {...restNativeProps} > {props.children} </button> ); }); CustomButton.displayName = 'CustomButton'; export default CustomButton;
此前Omit不生效的常见原因
- 仅做了类型层面的Omit声明,没有在运行时解构过滤属性,导致用户传入的
className/style仍然被透传给原生button元素 - Omit第二个参数拼写错误,比如大小写错误、单词拼写错误
- 类型交叉时引入了其他包含
className/style的类型,覆盖了Omit的排除效果,增加显式的never声明即可解决 - 未开启TypeScript严格模式,多余属性检查未生效,用户传入未定义属性时不会触发类型报错
内容的提问来源于stack exchange,提问作者The Lost JavaScripter
相关产品推荐
相关产品推荐

