Skip to content

Conversation

@m1abdullahh
Copy link
Contributor

@m1abdullahh m1abdullahh commented Dec 11, 2025

Fixing a bug

What?

This PR changes how the next option (with revalidate and tags) is typed for fetch requests. Instead of extending the global RequestInit interface, we now only patch the fetch() function signature to accept NextFetchRequestInit.

Why?

Previously, extending the global RequestInit interface created a type mismatch with runtime behavior. When using new Request({ next: {...} }), JavaScript's native Request constructor drops any properties that aren't part of the standard RequestInit interface, so the next option would be silently ignored. This created confusion because TypeScript would allow it, but it wouldn't actually work at runtime.

By restricting the next option to only be available through fetch() calls, we:

  • Align TypeScript types with actual runtime behavior
  • Prevent users from trying to use next with new Request() where it won't work
  • Make the API more explicit about where the next option is supported

How?

  1. Removed global RequestInit extension in packages/next/types/global.d.ts

    • Removed the interface extension that added next?: NextFetchRequestConfig to all RequestInit types
  2. Created NextFetchRequestInit type and augmented only fetch()

    • Added NextFetchRequestInit interface extending RequestInit with the next property
    • Used declare global to augment only the fetch() function signature to accept NextFetchRequestInit
    • Added export {} to make the file a module (required for global augmentations)
  3. Updated patched fetch implementation in packages/next/src/server/lib/patch-fetch.ts

    • Updated function signature to use NextFetchRequestInit instead of RequestInit
    • Added local type definitions for consistency

Now next can only be passed through fetch(), not through new Request(), which matches the actual runtime behavior.
Fixes #86898

@nextjs-bot
Copy link
Collaborator

nextjs-bot commented Dec 11, 2025

Allow CI Workflow Run

  • approve CI run for commit: 79bba26

Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer

Copy link
Contributor

@vercel vercel bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

The constructor parameter type RequestInit no longer has a next property after the PR changes, but line 417 attempts to access init?.next, which will cause a TypeScript compilation error.

View Details
📝 Patch Details
diff --git a/packages/next/src/server/lib/patch-fetch.ts b/packages/next/src/server/lib/patch-fetch.ts
index b0470a999a..4c02d77269 100644
--- a/packages/next/src/server/lib/patch-fetch.ts
+++ b/packages/next/src/server/lib/patch-fetch.ts
@@ -35,12 +35,12 @@ const isEdgeRuntime = process.env.NEXT_RUNTIME === 'edge'
 
 type Fetcher = typeof fetch
 
-interface NextFetchRequestConfig {
+export interface NextFetchRequestConfig {
   revalidate?: number | false
   tags?: string[]
 }
 
-interface NextFetchRequestInit extends RequestInit {
+export interface NextFetchRequestInit extends RequestInit {
   next?: NextFetchRequestConfig | undefined
 }
 
diff --git a/packages/next/src/server/web/sandbox/context.ts b/packages/next/src/server/web/sandbox/context.ts
index 431505ae51..cad54504e9 100644
--- a/packages/next/src/server/web/sandbox/context.ts
+++ b/packages/next/src/server/web/sandbox/context.ts
@@ -26,6 +26,10 @@ import {
   patchErrorInspectEdgeLite,
   patchErrorInspectNodeJS,
 } from '../../patch-error-inspect'
+import type {
+  NextFetchRequestConfig,
+  NextFetchRequestInit,
+} from '../../lib/patch-fetch'
 
 interface ModuleContext {
   runtime: EdgeRuntime
@@ -401,7 +405,7 @@ Learn More: https://nextjs.org/docs/messages/edge-dynamic-code-evaluation`),
       const __Request = context.Request
       context.Request = class extends __Request {
         next?: NextFetchRequestConfig | undefined
-        constructor(input: URL | RequestInfo, init?: RequestInit | undefined) {
+        constructor(input: URL | RequestInfo, init?: NextFetchRequestInit | undefined) {
           const url =
             typeof input !== 'string' && 'url' in input
               ? input.url

Analysis

TypeScript compilation error: Request constructor parameter type mismatch

What fails: The Request class in packages/next/src/server/web/sandbox/context.ts (line 408) accepts a constructor parameter init?: RequestInit | undefined but attempts to access init?.next (line 421). After PR commit 7a7b3f6a45 separated NextFetchRequestInit (which extends RequestInit with a next property) from the standard RequestInit type, the init parameter now lacks the next property, causing TypeScript strict mode compilation to fail.

How to reproduce:

# Run TypeScript compilation on the file (requires TypeScript setup)
# The file is included in packages/next/tsconfig.json with strict: true
# Attempting to compile will show:
# Property 'next' does not exist on type 'RequestInit | undefined'

Result: TypeScript compiler error at line 421: this.next = init?.next accesses property next which doesn't exist on type RequestInit. The code also references NextFetchRequestConfig on line 407 which was not imported, causing an additional undefined type error.

Expected: The constructor parameter should accept NextFetchRequestInit which extends RequestInit with the next property. This allows code to safely assign init?.next to the instance property.

Fix implemented:

  • Exported NextFetchRequestConfig and NextFetchRequestInit from packages/next/src/server/lib/patch-fetch.ts (where they are defined and centralized with fetch patching logic)
  • Added imports in packages/next/src/server/web/sandbox/context.ts
  • Updated constructor parameter type from RequestInit to NextFetchRequestInit which extends RequestInit while adding the next property support

This maintains backward compatibility since any code passing plain RequestInit values will still work (as NextFetchRequestInit extends RequestInit), while also properly supporting the next property when present.

Fix on Vercel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RequestInit shouldnt be extended with 'next' key ?

2 participants