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

在Next.js+TypeScript中扩展next/link时出现$$typeof属性缺失错误

问题:自定义Next.js Link组件的TypeScript类型错误与正确扩展方式

我希望基于Next.js的next/link创建链接API,编写了自定义Link组件,代码如下:

import NextLink from 'next/link'
import ExternalLink from './External'

type PropsType = typeof NextLink & {
  href: string
  children: React.ReactNode
}

export default function Link(props: PropsType) {
  return <NextLink {...props} />
}

Link.External = ExternalLink

ExternalLink组件代码为:

import React from 'react'

type ComponentPropsType = React.HTMLProps<HTMLAnchorElement> & {
  children: JSX.Element
  href: string
}

export default function Component({
  href,
  children,
  ...attrs
}: ComponentPropsType) {
  return <a {...attrs} target="_blank" rel="noreferrer" href={href}>{children}</a>
}

仅使用常规链接<Link href="/foo">Foo</Link>时,出现TypeScript错误:

Property '$$typeof' is missing in type '{ children: string; href: string; }' but required in type 'ForwardRefExoticComponent<Omit<AnchorHTMLAttributes, keyof InternalLinkProps> & InternalLinkProps & { ...; } & RefAttributes<...>>'.ts(2741)

Next.js的link.d.ts定义如下:

/// <reference types="node" />
import React from 'react';
import { UrlObject } from 'url';
declare type Url = string | UrlObject;
declare type InternalLinkProps = {
    href: Url;
    as?: Url;
    replace?: boolean;
    scroll?: boolean;
    shallow?: boolean;
    passHref?: boolean;
    prefetch?: boolean;
    locale?: string | false;
    legacyBehavior?: boolean;
    /**
     * requires experimental.newNextLinkBehavior
     */
    onMouseEnter?: (e: any) => void;
    /**
     * requires experimental.newNextLinkBehavior
     */
    onTouchStart?: (e: any) => void;
    /**
     * requires experimental.newNextLinkBehavior
     */
    onClick?: (e: any) => void;
};
export declare type LinkProps = InternalLinkProps;
declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof InternalLinkProps> & InternalLinkProps & {
    children?: React.ReactNode;
} & React.RefAttributes<HTMLAnchorElement>>;
export default Link;

请问当前写法哪里有误?如何正确进行类型定义以实现组件扩展?


解答

错误原因

你错误地将typeof NextLink(即组件本身的ForwardRefExoticComponent类型)当成了组件的props类型来使用。typeof NextLink代表的是整个Link组件的类型,而非它接收的props类型,这就导致传递普通的{href, children}对象时,无法满足组件类型的要求(比如缺少$$typeof这个React内部标识)。

正确的类型定义与组件扩展方式

1. 复用NextLink的Props类型

Next.js已经导出了LinkProps类型,我们可以直接复用它,或者通过React.ComponentProps<typeof NextLink>来获取NextLink的完整props类型,无需自己重新定义。

2. 修正自定义Link组件

将PropsType改为NextLink的props类型,同时正确处理组件的静态属性类型:

import NextLink from 'next/link'
import ExternalLink from './External'
import type { ComponentProps } from 'react'

// 获取NextLink的完整props类型
type LinkProps = ComponentProps<typeof NextLink>

// 定义自定义Link组件的类型,包含静态的External属性
type CustomLinkComponent = typeof NextLink & {
  External: typeof ExternalLink
}

export default function Link(props: LinkProps) {
  return <NextLink {...props} />
}

// 类型断言确保静态属性赋值符合类型要求
;(Link as CustomLinkComponent).External = ExternalLink

3. 修正ExternalLink组件的类型

原ExternalLink的children类型限制为JSX.Element过于严格,应该改为React.ReactNode以支持文本等非元素类型;同时推荐使用React.AnchorHTMLAttributes<HTMLAnchorElement>代替HTMLProps,类型更精准:

import React from 'react'

type ExternalLinkProps = React.AnchorHTMLAttributes<HTMLAnchorElement> & {
  href: string
  children: React.ReactNode
}

export default function ExternalLink({
  href,
  children,
  ...attrs
}: ExternalLinkProps) {
  return <a {...attrs} target="_blank" rel="noreferrer" href={href}>{children}</a>
}

4. 简化写法(可选)

如果不需要额外约束,也可以直接让自定义Link组件的props完全继承NextLink的类型,无需额外定义:

import NextLink from 'next/link'
import ExternalLink from './External'

// 直接使用NextLink的props类型
export default function Link(props: React.ComponentProps<typeof NextLink>) {
  return <NextLink {...props} />
}

// 类型断言处理静态属性
;(Link as typeof NextLink & { External: typeof ExternalLink }).External = ExternalLink

这样修改后,使用<Link href="/foo">Foo</Link>就不会再出现TypeScript错误,同时也正确扩展了Link.External静态组件。


内容的提问来源于stack exchange,提问作者Lance Pollard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 20:55:21