Next.js TypeScript项目自定义LinkButton组件Props解构报错求助
问题分析与解决
这不是size类型的问题,也不是TypeScript的Bug,核心原因是多类型交叉后,TypeScript无法正确推断剩余属性rest的对象类型,再加上代码里的写法错误,最终触发了报错。
具体原因
当你把ButtonProps、LinkProps和HTMLProps<HTMLAnchorElement>交叉合并时:
HTMLProps<HTMLAnchorElement>本身包含onClick属性(类型为MouseEventHandler<HTMLAnchorElement>),而你的ButtonProps里也定义了onClick: () => void,两个类型交叉后产生冲突,干扰了TypeScript对rest的类型解析。- 手动解构NextLink的属性后,剩余的
rest被TS判定为非纯对象类型,于是抛出Rest types may only be created from object types错误。移除size后TS的类型推断逻辑刚好避开了冲突判定,错误暂时消失,但这只是巧合,并非根本解决方法。
修正方案
1. 修复Button组件的调用错误
你代码里的<Button ...ButtonProps/>写法错误,应该把rest中属于Button的属性传递给组件:
<Button {...rest} />
2. 明确rest类型,规避交叉冲突
用Omit工具类型排除LinkProps的属性,同时去掉HTMLProps中和ButtonProps冲突的字段,让TS清晰识别rest的纯对象类型:
import NextLink, { LinkProps } from 'next/link' import { HTMLProps, FC, MouseEventHandler } from 'react' import { GlobalColorsType } from '../../types' import Button from './Button' type ButtonProps = { type: GlobalColorsType size: 'xs' | 's' | 'm' | 'l' | 'xl' onClick: MouseEventHandler<HTMLButtonElement> // 建议和Button组件的onClick类型对齐,避免冲突 className?: string id?: string style?: any } // 排除LinkProps属性,同时移除HTMLProps中和ButtonProps冲突的onClick type LinkButtonProps = Omit<HTMLProps<HTMLAnchorElement>, 'onClick'> & ButtonProps & LinkProps const LinkButton: FC<LinkButtonProps> = ({ as, children, href, replace, scroll, shallow, passHref, ...rest // TS现在能明确这是纯对象类型 }) => ( <NextLink as={as} href={href} passHref={passHref} replace={replace} scroll={scroll} shallow={shallow} > <a {...rest}> <Button {...rest} /> </a> </NextLink> ) export default LinkButton
3. 可选优化:拆分属性传递
如果不想用Omit,可以手动拆分Button和a标签的属性,避免类型混淆:
const LinkButton: FC<LinkButtonProps> = ({ as, children, href, replace, scroll, shallow, passHref, // 手动提取Button所需属性 type, size, onClick, // 提取a标签所需属性 className, id, style, ...anchorRest }) => ( <NextLink as={as} href={href} passHref={passHref} replace={replace} scroll={scroll} shallow={shallow} > <a className={className} id={id} style={style} {...anchorRest}> <Button type={type} size={size} onClick={onClick} className={className} id={id} style={style} /> </a> </NextLink> )
内容的提问来源于stack exchange,提问作者robicano22
相关产品推荐
相关产品推荐

