fix: patch fetch() signature instead of extending RequestInit
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
nextwithnew Request()where it won't work - Make the API more explicit about where the
nextoption is supported
How?
-
Removed global
RequestInitextension inpackages/next/types/global.d.ts- Removed the interface extension that added
next?: NextFetchRequestConfigto allRequestInittypes
- Removed the interface extension that added
-
Created
NextFetchRequestInittype and augmented onlyfetch()- Added
NextFetchRequestInitinterface extendingRequestInitwith thenextproperty - Used
declare globalto augment only thefetch()function signature to acceptNextFetchRequestInit - Added
export {}to make the file a module (required for global augmentations)
- Added
-
Updated patched fetch implementation in
packages/next/src/server/lib/patch-fetch.ts- Updated function signature to use
NextFetchRequestInitinstead ofRequestInit - Added local type definitions for consistency
- Fixed TypeScript compatibility issues with newer fetch type definitions
- Updated function signature to use
Now next can only be passed through fetch(), not through new Request(), which matches the actual runtime behavior.
Fixes #86898
Allow CI Workflow Run
- [ ] approve CI run for commit: 79bba26fe080f00e52a7f7d8d5633b41c61218ba
Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer
Great fix! 👍
This approach is much cleaner than extending RequestInit globally. By patching the fetch() signature directly with NextFetchRequestInit, you're:
- ✅ Preventing the
nextoption from leaking into non-Next.js fetch calls - ✅ Maintaining proper TypeScript type safety
- ✅ Following the pattern of augmenting global scope in a module context
The implementation looks solid. The type casting in patch-fetch.ts is appropriate since we're intentionally narrowing the signature for Next.js-specific behavior.
One minor suggestion: Consider adding a JSDoc comment to NextFetchRequestInit explaining that this is Next.js's extended fetch signature, to help developers understand why it exists separately from the standard RequestInit.
Otherwise, LGTM! 🚀