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

Next.js中如何为next/link的Link传递正确TypeScript类型

解决Next.js Link组件与原生a标签切换时的TypeScript类型定义问题

问题场景

我刚接触TypeScript,重构代码时遇到自定义函数参数的类型定义难题:需要根据路由判断,在Next.js的NextLink组件和原生a标签之间切换,但始终无法给函数参数设置正确的类型。简化代码如下:

utility.ts

export function getLinkAndProps (route: string, nextLink: ??) {  // 尝试传入next/link的LinkProps但匹配失败
    const Link = (route === "/works" || route === "/books") ? nextLink : "a"
    const linkProps = Link === "a" ? {rel:"noopener noreferrer", target: "_blank"} : {scroll: false};
    return {
        Link,
        linkProps
    }
}
import NextLink from "next/link";
import { getLinkAndProps } from "@/utils/utility";

const LinkItem = ({ children, href, path }: LinkItemProps) => {
    const active = path === href;
    const { Link, linkProps } = getLinkAndProps(href, NextLink) // TypeScript报错:NextLink缺少'href'属性

    return (
        <Link href={href} {...linkProps}>
            {children}
        </Link>
    );
}

用any类型能临时解决问题,但我想找到符合TypeScript规范的类型定义方式。曾查看Next.js Link源码写出了可行但冗余的类型:

import { LinkProps } from "next/link";

type TestProps = React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> & LinkProps & {
    children?: React.ReactNode;
} & React.RefAttributes<HTMLAnchorElement>>;

后来想到第二个参数不会变动,直接在函数内导入NextLink应该可行,但还是想明确正确的类型定义方法。


解决方案

方案1:直接复用NextLink的类型

不需要手动拼接复杂类型,用typeof NextLink就能直接获取NextLink组件的构造函数类型,完美匹配传入的组件实例:

修改utility.ts:

import type { NextLink } from "next/link";

export function getLinkAndProps(route: string, nextLink: typeof NextLink) {
    const Link = (route === "/works" || route === "/books") ? nextLink : "a";
    const linkProps = Link === "a" 
        ? { rel: "noopener noreferrer", target: "_blank" } 
        : { scroll: false };
    return {
        Link,
        linkProps
    } as const; // 用as const让TS推导更精确的返回类型
}

as const会让TypeScript严格推导返回值的类型,确保Link和linkProps的类型一一对应,避免后续使用时出现类型不匹配的问题。

方案2:函数内直接导入NextLink(简化版)

既然NextLink参数不会变动,完全可以在getLinkAndProps内部直接导入,省去传参和类型定义的麻烦:

修改utility.ts:

import NextLink from "next/link";

export function getLinkAndProps(route: string) {
    const Link = (route === "/works" || route === "/books") ? NextLink : "a";
    const linkProps = Link === "a" 
        ? { rel: "noopener noreferrer", target: "_blank" } 
        : { scroll: false };
    return {
        Link,
        linkProps
    } as const;
}

调用时无需传NextLink:

const { Link, linkProps } = getLinkAndProps(href);

方案3:手动定义返回类型(增强可读性)

如果需要更明确的类型约束,可以手动定义返回类型,让代码逻辑更清晰:

import NextLink from "next/link";

type LinkReturnType = 
    | { Link: typeof NextLink; linkProps: { scroll: boolean } }
    | { Link: "a"; linkProps: { rel: string; target: string } };

export function getLinkAndProps(route: string): LinkReturnType {
    const Link = (route === "/works" || route === "/books") ? NextLink : "a";
    const linkProps = Link === "a" 
        ? { rel: "noopener noreferrer", target: "_blank" } 
        : { scroll: false };
    return {
        Link,
        linkProps
    } as LinkReturnType;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:45:19