React+TS创建可复用Button组件遇"Not assignable"错误
问题描述
在React + TypeScript项目中自定义Button组件时,声明Props的type属性遇到如下类型不兼容错误:
Type 'DetailedHTMLProps<ButtonHTMLAttributes
, HTMLButtonElement>' is not assignable to type '"button" | "reset" | "submit" | undefined'.ts(2322) index.d.ts(2086, 9): The expected type comes from property 'type' which is declared here on type 'DetailedHTMLProps<ButtonHTMLAttributes
, HTMLButtonElement>'
尝试过自定义enum、错误提示建议的类型、旧GitHub议题中的方案均无效,怀疑是版本更新或tsconfig配置问题,原代码如下:
import React from 'react'; enum ButtonTypes { 'button', 'submit', 'reset', undefined } type Props = { text: string; type: React.ComponentProps<'button'>; // ButtonTypes throws the same error onClick: Function | null; }; function Button({ text, type, onClick }: Props) { return ( <button className='className="bg-primary text-base-100 font-display font-light self-center mt-5 px-3 py-2"' type={type} > {text} </button> ); } export default Button;
错误原因分析
type属性类型声明错误:React.ComponentProps<'button'>是原生button组件的完整Props类型,而非单个type属性的类型,直接赋值会导致类型不匹配。- 自定义
enum写法错误:enum不能直接将undefined作为成员,且未显式赋值字符串时,enum默认是数字索引类型,和原生button的type字符串类型不兼容。 onClick类型宽泛:使用Function作为事件处理类型不够精确,不符合React事件处理的类型规范。
修正方案
方案一:复用原生button的type属性类型
直接从React内置的button属性类型中提取type的类型,最贴合原生规范:
import React from 'react'; type Props = { text: string; // 提取原生button的type属性类型,设为可选 type?: React.ButtonHTMLAttributes<HTMLButtonElement>['type']; // 使用React官方事件处理类型,更安全精确 onClick?: React.MouseEventHandler<HTMLButtonElement> | null; }; function Button({ text, type = 'button', onClick }: Props) { return ( <button className="bg-primary text-base-100 font-display font-light self-center mt-5 px-3 py-2" type={type} onClick={onClick} > {text} </button> ); } export default Button;
方案二:使用正确的enum类型
如果需要用enum约束type的可选值,需显式给enum成员赋值为对应字符串:
import React from 'react'; // 显式赋值字符串,确保和原生type类型匹配 enum ButtonType { Button = 'button', Submit = 'submit', Reset = 'reset' } type Props = { text: string; type?: ButtonType; onClick?: React.MouseEventHandler<HTMLButtonElement> | null; }; function Button({ text, type = ButtonType.Button, onClick }: Props) { return ( <button className="bg-primary text-base-100 font-display font-light self-center mt-5 px-3 py-2" type={type} onClick={onClick} > {text} </button> ); } export default Button;
注意事项
- 避免将完整的
ComponentProps<'button'>赋值给单个属性,需提取对应属性的类型。 - enum成员必须显式赋值为目标字符串,否则会出现数字类型和字符串类型不兼容的问题。
- 事件处理函数优先使用React提供的专属类型(如
MouseEventHandler),避免泛用Function。 - 给
type属性设置可选性和默认值,符合原生button的默认行为(默认type为button)。
内容的提问来源于stack exchange,提问作者LeperAffinity666
相关产品推荐
相关产品推荐

