nextjs - 💡(How to fix) Fix next/link JSX type error when typedRoutes: true enabled [3 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#86156Fetched 2026-04-08 02:12:15
View on GitHub
Comments
3
Participants
3
Timeline
6
Reactions
0
Timeline (top)
commented ×3issue_type_added ×1labeled ×1referenced ×1

Error Message

next build

▲ Next.js 16.0.3 (Turbopack)

Creating an optimized production build ... ✓ Compiled successfully in 2.6s Running TypeScript .Failed to compile.

./src/app/test/page.tsx:6:8 Type error: 'Link' cannot be used as a JSX component. Its type '{ <RouteType>(props: LinkProps<RouteType>): Element; <RouteType>(props: LinkProps<RouteType>): Element; }' is not a valid JSX element type. Type '{ <RouteType>(props: LinkProps<RouteType>): Element; <RouteType>(props: LinkProps<RouteType>): Element; }' is not assignable to type '(props: any) => ReactNode | Promise<ReactNode>'. Type 'Element' is not assignable to type 'ReactNode | Promise<ReactNode>'. Property 'children' is missing in type 'ReactElement<any, any>' but required in type 'ReactPortal'.

4 | return ( 5 | <div>

6 | <Link href="/">Home</Link> | ^ 7 | </div> 8 | ); 9 | } Next.js build worker exited with code: 1 and signal: null  ELIFECYCLE  Command failed with exit code 1.

Code Example

npx create-next-app@latest my-app
cd my-app

---

pnpm install

---

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  typedRoutes: true,
};

export default nextConfig;

---

import React from "react";
import Link from "next/link";

export default function page() {
  return (
    <div>
      <Link href="/" className="text-blue-500 hover:underline">
        Home
      </Link>
    </div>
  );
}

---

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint"
  },
  "dependencies": {
    "next": "16.0.3",
    "react": "19.2.0",
    "react-dom": "19.2.0"
  },
  "devDependencies": {
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "16.0.3",
    "tailwindcss": "^4",
    "typescript": "^5"
  }
}

---

pnpm run build

---

'Link' cannot be used as a JSX component.
  Its type '<RouteType>(props: LinkProps<RouteType>) => Element' is not a valid JSX element type.
    Type '<RouteType>(props: LinkProps<RouteType>)' is not assignable to type '(props: any) => ReactNode | Promise<ReactNode>'.
      Type 'Element' is not assignable to type 'ReactNode | Promise<ReactNode>'.
        Property 'children' is missing in type 'ReactElement<any, any>' but required in type 'ReactPortal'.

---

// This file is generated automatically by Next.js
// Do not edit this file manually

type AppRoutes = "/" | "/test"
type PageRoutes = never
type LayoutRoutes = "/"
type RedirectRoutes = never
type RewriteRoutes = never
type Routes = AppRoutes | PageRoutes | LayoutRoutes | RedirectRoutes | RewriteRoutes


interface ParamMap {
  "/": {}
  "/test": {}
}


export type ParamsOf<Route extends Routes> = ParamMap[Route]

interface LayoutSlotMap {
  "/": never
}


export type { AppRoutes, PageRoutes, LayoutRoutes, RedirectRoutes, RewriteRoutes, ParamMap }

declare global {
  /**
   * Props for Next.js App Router page components
   * @example
   *

---

*/
  interface PageProps<AppRoute extends AppRoutes> {
    params: Promise<ParamMap[AppRoute]>
    searchParams: Promise<Record<string, string | string[] | undefined>>
  }

  /**
   * Props for Next.js App Router layout components
   * @example
   *

---

*/
  type LayoutProps<LayoutRoute extends LayoutRoutes> = {
    params: Promise<ParamMap[LayoutRoute]>
    children: React.ReactNode
  } & {
    [K in LayoutSlotMap[LayoutRoute]]: React.ReactNode
  }
}

---

> next build

Next.js 16.0.3 (Turbopack)

   Creating an optimized production build ...
Compiled successfully in 2.6s
   Running TypeScript  .Failed to compile.

./src/app/test/page.tsx:6:8
Type error: 'Link' cannot be used as a JSX component.
  Its type '{ <RouteType>(props: LinkProps<RouteType>): Element; <RouteType>(props: LinkProps<RouteType>): Element; }' is not a valid JSX element type.
    Type '{ <RouteType>(props: LinkProps<RouteType>): Element; <RouteType>(props: LinkProps<RouteType>): Element; }' is not assignable to type '(props: any) => ReactNode | Promise<ReactNode>'.
      Type 'Element' is not assignable to type 'ReactNode | Promise<ReactNode>'.
        Property 'children' is missing in type 'ReactElement<any, any>' but required in type 'ReactPortal'.

  4 |   return (
  5 |     <div>
> 6 |       <Link href="/">Home</Link>
    |        ^
  7 |     </div>
  8 |   );
  9 | }
Next.js build worker exited with code: 1 and signal: null
ELIFECYCLECommand failed with exit code 1.

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.6.0
Binaries:
  Node: 20.17.0
  npm: 10.8.2
  Yarn: 1.22.22
  pnpm: 9.10.0
Relevant Packages:
  next: 16.0.3
  eslint-config-next: 16.0.3
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.2.0
Next.js Config:
  typedRoutes: true
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/faridvatani/next-link-typedroutes-ts-error

To Reproduce

  1. Create a new Next.js project using the latest version:
npx create-next-app@latest my-app
cd my-app
  1. Install dependencies (default from create-next-app):
pnpm install
  1. Update next.config.ts to enable typed routes:
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  typedRoutes: true,
};

export default nextConfig;
  1. Create a test page at src/app/test/page.tsx:
import React from "react";
import Link from "next/link";

export default function page() {
  return (
    <div>
      <Link href="/" className="text-blue-500 hover:underline">
        Home
      </Link>
    </div>
  );
}
  1. Your package.json should match:
{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint"
  },
  "dependencies": {
    "next": "16.0.3",
    "react": "19.2.0",
    "react-dom": "19.2.0"
  },
  "devDependencies": {
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "16.0.3",
    "tailwindcss": "^4",
    "typescript": "^5"
  }
}
  1. Build the project.
pnpm run build
  1. Observe the TypeScript error:
'Link' cannot be used as a JSX component.
  Its type '<RouteType>(props: LinkProps<RouteType>) => Element' is not a valid JSX element type.
    Type '<RouteType>(props: LinkProps<RouteType>)' is not assignable to type '(props: any) => ReactNode | Promise<ReactNode>'.
      Type 'Element' is not assignable to type 'ReactNode | Promise<ReactNode>'.
        Property 'children' is missing in type 'ReactElement<any, any>' but required in type 'ReactPortal'.

  1. The .next/types/routes.d.ts file:
// This file is generated automatically by Next.js
// Do not edit this file manually

type AppRoutes = "/" | "/test"
type PageRoutes = never
type LayoutRoutes = "/"
type RedirectRoutes = never
type RewriteRoutes = never
type Routes = AppRoutes | PageRoutes | LayoutRoutes | RedirectRoutes | RewriteRoutes


interface ParamMap {
  "/": {}
  "/test": {}
}


export type ParamsOf<Route extends Routes> = ParamMap[Route]

interface LayoutSlotMap {
  "/": never
}


export type { AppRoutes, PageRoutes, LayoutRoutes, RedirectRoutes, RewriteRoutes, ParamMap }

declare global {
  /**
   * Props for Next.js App Router page components
   * @example
   * ```tsx
   * export default function Page(props: PageProps<'/blog/[slug]'>) {
   *   const { slug } = await props.params
   *   return <div>Blog post: {slug}</div>
   * }
   * ```
   */
  interface PageProps<AppRoute extends AppRoutes> {
    params: Promise<ParamMap[AppRoute]>
    searchParams: Promise<Record<string, string | string[] | undefined>>
  }

  /**
   * Props for Next.js App Router layout components
   * @example
   * ```tsx
   * export default function Layout(props: LayoutProps<'/dashboard'>) {
   *   return <div>{props.children}</div>
   * }
   * ```
   */
  type LayoutProps<LayoutRoute extends LayoutRoutes> = {
    params: Promise<ParamMap[LayoutRoute]>
    children: React.ReactNode
  } & {
    [K in LayoutSlotMap[LayoutRoute]]: React.ReactNode
  }
}

Current vs. Expected behavior

Current: Compilation fails with the following error:

> next build

   ▲ Next.js 16.0.3 (Turbopack)

   Creating an optimized production build ...
 ✓ Compiled successfully in 2.6s
   Running TypeScript  .Failed to compile.

./src/app/test/page.tsx:6:8
Type error: 'Link' cannot be used as a JSX component.
  Its type '{ <RouteType>(props: LinkProps<RouteType>): Element; <RouteType>(props: LinkProps<RouteType>): Element; }' is not a valid JSX element type.
    Type '{ <RouteType>(props: LinkProps<RouteType>): Element; <RouteType>(props: LinkProps<RouteType>): Element; }' is not assignable to type '(props: any) => ReactNode | Promise<ReactNode>'.
      Type 'Element' is not assignable to type 'ReactNode | Promise<ReactNode>'.
        Property 'children' is missing in type 'ReactElement<any, any>' but required in type 'ReactPortal'.

  4 |   return (
  5 |     <div>
> 6 |       <Link href="/">Home</Link>
    |        ^
  7 |     </div>
  8 |   );
  9 | }
Next.js build worker exited with code: 1 and signal: null
 ELIFECYCLE  Command failed with exit code 1.

Expected: The Link component can be used as usual in JSX, as per the Next.js documentation, without causing type errors.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.6.0
Binaries:
  Node: 20.17.0
  npm: 10.8.2
  Yarn: 1.22.22
  pnpm: 9.10.0
Relevant Packages:
  next: 16.0.3
  eslint-config-next: 16.0.3
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.2.0
Next.js Config:
  typedRoutes: true

Which area(s) are affected? (Select all that apply)

TypeScript

Which stage(s) are affected? (Select all that apply)

next build (local)

Additional context

No response

extent analysis

TL;DR

The issue is likely due to a type mismatch between the Link component and the expected JSX element type, and can be fixed by updating the Link component to match the expected type.

Guidance

  • Check the type definitions for the Link component and the expected JSX element type to identify the specific type mismatch.
  • Verify that the Link component is being used correctly and that the href prop is being passed a valid route.
  • Consider updating the @types/next package to ensure that the type definitions are up-to-date.
  • If using a custom Link component, ensure that it is correctly typed and compatible with the expected JSX element type.

Example

import Link from 'next/link';

// Update the Link component to match the expected type
const CustomLink = ({ href, children }: { href: string; children: React.ReactNode }) => {
  return <Link href={href}>{children}</Link>;
};

Notes

The issue appears to be related to the typedRoutes feature in Next.js, which may require additional type definitions or updates to the @types/next package.

Recommendation

Apply a workaround by updating the Link component to match the expected type, as shown in the example above. This should resolve the type error and allow the project to build successfully.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING