Skip to content

Conversation

@0372hoanghoccode
Copy link

@0372hoanghoccode 0372hoanghoccode commented Jan 22, 2026

Fixes #14734

Summary

This PR fixes TypeScript compatibility when exactOptionalPropertyTypes: true is enabled in tsconfig.json.

Problem

When exactOptionalPropertyTypes is enabled, TypeScript requires optional properties to explicitly allow undefined. The generated types from react-router typegen were causing type errors:

Type 'undefined' is not assignable to type 'Func'

This occurred because:

  • Route modules have optional exports like action?: () => {...}
  • When importing: typeof import('./root') → { action: (() => ...) | undefined }
  • With exactOptionalPropertyTypes: true: action?: Func ≠ action: Func | undefined

Solution

  1. Added StrictOptionals type helper in packages/react-router/lib/types/utils.ts

    • Converts { action: Func | undefined } to { action?: Func }
  2. Runtime detection in packages/react-router-dev/typegen/generate.ts

    • Detects exactOptionalPropertyTypes setting in tsconfig.json
  3. Conditional type wrapping in generated code

    • When exactOptionalPropertyTypes: true: type Module = StrictOptionals<typeof import(...)>
    • Otherwise: type Module = typeof import(...)
  4. Exported StrictOptionals via react-router/internal for generated code to use

Testing

  • Added integration test exactOptionalPropertyTypes compatibility in integration/typegen-test.ts
  • Verifies type inference works correctly with exactOptionalPropertyTypes: true

Changes

  • packages/react-router/lib/types/utils.ts - Added StrictOptionals type
  • packages/react-router/lib/types/internal.ts - Exported StrictOptionals
  • packages/react-router-dev/typegen/generate.ts - Detection and conditional wrapping
  • integration/typegen-test.ts - Integration test
  • .changeset/fix-exact-optional-property-types.md - Changeset

@changeset-bot
Copy link

changeset-bot bot commented Jan 22, 2026

🦋 Changeset detected

Latest commit: 08d06ec

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
react-router Patch
@react-router/dev Patch
@react-router/architect Patch
@react-router/cloudflare Patch
react-router-dom Patch
@react-router/express Patch
@react-router/node Patch
@react-router/serve Patch
@react-router/fs-routes Patch
@react-router/remix-routes-option-adapter Patch
create-react-router Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@remix-cla-bot
Copy link
Contributor

remix-cla-bot bot commented Jan 22, 2026

Hi @0372hoanghoccode,

Welcome, and thank you for contributing to React Router!

Before we consider your pull request, we ask that you sign our Contributor License Agreement (CLA). We require this only once.

You may review the CLA and sign it by adding your name to contributors.yml.

Once the CLA is signed, the CLA Signed label will be added to the pull request.

If you have already signed the CLA and received this response in error, or if you have any questions, please contact us at hello@remix.run.

Thanks!

- The Remix team

@remix-cla-bot
Copy link
Contributor

remix-cla-bot bot commented Jan 22, 2026

Thank you for signing the Contributor License Agreement. Let's get this merged! 🥳

The test was using path.join() which creates platform-specific paths
(backslashes on Windows), then mixing it with path.posix.join().
This caused path.posix.relative() to calculate incorrect relative paths
on Windows, expecting "../routes/route.tsx" but getting "../../../routes/route.tsx".

Changed to use path.posix.join() consistently for cross-platform compatibility.
@0372hoanghoccode
Copy link
Author

I've fixed the Windows test failure in flatRoutes-test.ts by using path.posix.join for cross-platform compatibility.

The remaining CI failures (route-config-test.ts, data-browser-router-test.tsx, special-characters-test.tsx) are pre-existing issues in the dev branch - they also fail when testing dev directly on Windows. These failures are not related to my TypeScript changes for exactOptionalPropertyTypes.

My changes only modified:

  • TypeScript type definitions to support exactOptionalPropertyTypes: true
  • Fixed Windows path issue in flatRoutes-test.ts

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.

2 participants