Skip to content

next-env.d.ts changes route type import between next dev and next typegen #94153

@IFAKA

Description

@IFAKA

Link to the code that reproduces this issue

https://github.com/IFAKA/next-env-dts-churn-repro

To Reproduce

The repro is based on the official reproduction-template, uses TypeScript/App Router, and intentionally tracks next-env.d.ts so the generated-file churn is visible as a Git diff.

npm run typecheck
sed -n '1,6p' next-env.d.ts
npm run dev
# stop dev after Ready
sed -n '1,6p' next-env.d.ts
git diff -- next-env.d.ts
npm run typecheck
sed -n '1,6p' next-env.d.ts

The added script is:

"typecheck": "next typegen && tsc --noEmit"

Current vs. Expected behavior

Current behavior: the root generated next-env.d.ts changes depending on command order.

After next typegen / npm run typecheck:

/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
import "./.next/types/root-params.d.ts";

After next dev:

/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/dev/types/root-params.d.ts";

Observed diff after starting next dev from a committed next typegen baseline:

diff --git a/next-env.d.ts b/next-env.d.ts
index ce4e94a..a419cbe 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,7 +1,7 @@
 /// <reference types="next" />
 /// <reference types="next/image-types/global" />
-import "./.next/types/routes.d.ts";
-import "./.next/types/root-params.d.ts";
+import "./.next/dev/types/routes.d.ts";
+import "./.next/dev/types/root-params.d.ts";
 
 // NOTE: This file should not be edited
 // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

Running npm run typecheck again passes and flips the imports back to .next/types/....

Expected behavior: either the generated root next-env.d.ts output stays stable across local commands, or docs/tooling more clearly guide users toward ignoring the file and running next typegen before standalone tsc.

I know the docs already recommend ignoring next-env.d.ts:

That mitigation works locally. This issue is for the churn that still appears when a project has historically tracked the file, which makes next dev and next typegen fight over the checked-in content.

Related context:

Provide environment information

From the repro with Node 25.6.1:

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.5.0: Mon Apr 27 20:41:15 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T6041
  Available memory (MB): 49152
  Available CPU cores: 12
Binaries:
  Node: 25.6.1
  npm: 11.12.1
  Yarn: 1.22.22
  pnpm: 10.25.0
Relevant Packages:
  next: 16.3.0-canary.30 // Latest available version is detected (16.3.0-canary.30).
  eslint-config-next: N/A
  react: 19.2.6
  react-dom: 19.2.6
  typescript: 5.9.3
Next.js Config:
  output: N/A

Additional project evidence where this was noticed:

Declared Next range: ^16.1.0
Installed Next version: 16.2.6
Node: 25.6.1
TypeScript: 5.9.3

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

TypeScript

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

next dev (local), Other (next typegen)

Additional context

This is intentionally not a PR because the previous stability fix in #88428 was reverted in #90384 after causing generated type correctness issues. A docs/tooling clarification may be safer than changing the generated import target again, but I wanted to provide a current canary repro for the remaining churn.

Metadata

Metadata

Assignees

No one assigned

    Labels

    TypeScriptRelated to types with Next.js.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions