You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+TS创建可复用Button组件遇"Not assignable"错误

React + TS 自定义Button组件Props类型错误解决方法

问题描述

在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;

错误原因分析

  1. type属性类型声明错误:React.ComponentProps<'button'>是原生button组件的完整Props类型,而非单个type属性的类型,直接赋值会导致类型不匹配。
  2. 自定义enum写法错误:enum不能直接将undefined作为成员,且未显式赋值字符串时,enum默认是数字索引类型,和原生button的type字符串类型不兼容。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:50:39