-
Notifications
You must be signed in to change notification settings - Fork 30.2k
fix: patch fetch() signature instead of extending RequestInit #87072
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: canary
Are you sure you want to change the base?
fix: patch fetch() signature instead of extending RequestInit #87072
Conversation
|
Allow CI Workflow Run
Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer |
There was a problem hiding this 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
NextFetchRequestConfigandNextFetchRequestInitfrompackages/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
RequestInittoNextFetchRequestInitwhich extendsRequestInitwhile adding thenextproperty 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.
Fixing a bug
What?
This PR changes how the
nextoption (withrevalidateandtags) is typed for fetch requests. Instead of extending the globalRequestInitinterface, we now only patch thefetch()function signature to acceptNextFetchRequestInit.Why?
Previously, extending the global
RequestInitinterface created a type mismatch with runtime behavior. When usingnew Request({ next: {...} }), JavaScript's nativeRequestconstructor drops any properties that aren't part of the standardRequestInitinterface, so thenextoption would be silently ignored. This created confusion because TypeScript would allow it, but it wouldn't actually work at runtime.By restricting the
nextoption to only be available throughfetch()calls, we:nextwithnew Request()where it won't worknextoption is supportedHow?
Removed global
RequestInitextension inpackages/next/types/global.d.tsnext?: NextFetchRequestConfigto allRequestInittypesCreated
NextFetchRequestInittype and augmented onlyfetch()NextFetchRequestInitinterface extendingRequestInitwith thenextpropertydeclare globalto augment only thefetch()function signature to acceptNextFetchRequestInitexport {}to make the file a module (required for global augmentations)Updated patched fetch implementation in
packages/next/src/server/lib/patch-fetch.tsNextFetchRequestInitinstead ofRequestInitNow
nextcan only be passed throughfetch(), not throughnew Request(), which matches the actual runtime behavior.Fixes #86898