Skip to content

feat(router-generator): add isolatedDeclarations config option#7289

Draft
guru-irl wants to merge 3 commits intoTanStack:mainfrom
guru-irl:feat/router-generator-isolated-declarations
Draft

feat(router-generator): add isolatedDeclarations config option#7289
guru-irl wants to merge 3 commits intoTanStack:mainfrom
guru-irl:feat/router-generator-isolated-declarations

Conversation

@guru-irl
Copy link
Copy Markdown

@guru-irl guru-irl commented Apr 29, 2026

Summary

When a project enables TypeScript's --isolatedDeclarations (or the equivalent oxc setting), the route tree generated by router-generator currently triggers TS9010:

error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations.
  const PostsRoute = PostsRouteImport.update({...} as any)
                                                        ^

This happens because the type of PostsRoute must be inferred from the return type of .update() — which crosses a file boundary, violating the isolated-declarations constraint.

Solution

Add an isolatedDeclarations boolean option to tsr.config.json (defaults to false). When enabled, the generator emits explicit : any annotations on route constants:

// Before (fails with --isolatedDeclarations)
const PostsRoute = PostsRouteImport.update({...} as any)

// After (isolatedDeclarations: true)
const PostsRoute: any = PostsRouteImport.update({...} as any)

The option is opt-in to avoid any impact on existing users. It is a no-op when disableTypes: true.

Type safety tradeoff

Using : any on route constants means typeof PostsRoute === any, which does collapse the router's type tree (breaking useRouteContext, useParams inference etc.). This is an accepted tradeoff for projects that need isolatedDeclarations compliance — they already pay the same price for other as any patterns in the generated file.

A future improvement could use a more precise type (e.g. the specific Route class type), but that would require the generator to know the exact return type of .update(), which is not currently feasible.

Test plan

  • Added isolated-declarations generator test fixture (copied from single-level)
  • Snapshot asserts : any is emitted on route constants when option is enabled
  • All 234 existing generator tests pass unchanged (option defaults to false)
  • tsc proof: const X = import.update({} as any) + export interface I { '/': typeof X } → TS9010 without : any, clean with : any

Summary by CodeRabbit

Release Notes

  • New Features

    • Added isolatedDeclarations configuration option to the router generator for enhanced type handling in route declarations.
  • Tests

    • Added test coverage for the new isolatedDeclarations configuration.

When `isolatedDeclarations: true` is set in tsr.config.json, the generator
emits explicit `: any` type annotations on route constants:

  const PostsRoute: any = PostsRouteImport.update({...} as any)

Without this annotation, TypeScript and oxc raise TS9010 ("Variable must have
an explicit type annotation with --isolatedDeclarations") because the return
type of `.update()` must be inferred across files.

The option defaults to `false` to preserve existing behaviour. It is a no-op
when `disableTypes: true` (JS output).

Adds an `isolated-declarations` test fixture (copied from `single-level`) with
a snapshot that asserts the `: any` annotations are emitted.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 29, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eee340d8-d827-4630-8adc-b0a677a925dc

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request introduces a new optional configuration flag, isolatedDeclarations, to the router generator. When enabled in combination with type generation, the generator conditionally adds a : any type annotation to generated route constants. Test fixtures and snapshots are provided to validate the feature.

Changes

Cohort / File(s) Summary
Configuration & Core Logic
packages/router-generator/src/config.ts, packages/router-generator/src/generator.ts
Adds isolatedDeclarations optional boolean flag (default false) to the configuration schema, and conditionally applies : any type annotation to generated route constants when this flag is enabled with types.
Test Configuration
packages/router-generator/tests/generator.test.ts
Registers a new test case configuration path for isolated-declarations to run the generator with the flag enabled.
Test Fixtures & Generated Snapshot
packages/router-generator/tests/generator/isolated-declarations/routes/__root.tsx, packages/router-generator/tests/generator/isolated-declarations/routes/index.tsx, packages/router-generator/tests/generator/isolated-declarations/routes/posts.tsx, packages/router-generator/tests/generator/isolated-declarations/routeTree.snapshot.ts
Provides test route fixtures and an auto-generated route tree snapshot demonstrating the output when isolatedDeclarations is enabled.

Poem

🐰 A flag so fine, isolatedDeclarations declared,
Type annotations added where routes are prepared,
Conditional logic, gentle and neat,
Making router generation more complete! ✨

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a new isolatedDeclarations config option to router-generator, which is the primary feature introduced across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 29, 2026

Bundle Size Benchmarks

  • Commit: d6decca41807
  • Measured at: 2026-04-29T14:28:02.557Z
  • Baseline source: history:d6decca41807
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.30 KiB 0 B (0.00%) 274.68 KiB 75.83 KiB ████████▁▁▁
react-router.full 90.80 KiB 0 B (0.00%) 286.19 KiB 79.00 KiB ▁▁▁▁▁▁▁▁███
solid-router.minimal 35.55 KiB 0 B (0.00%) 106.95 KiB 31.97 KiB ▁▁▁▁████▁▁▁
solid-router.full 40.28 KiB 0 B (0.00%) 121.16 KiB 36.16 KiB ▁▁▁▁▄███▄▄▄
vue-router.minimal 53.30 KiB 0 B (0.00%) 152.09 KiB 47.88 KiB ████████▁▁▁
vue-router.full 58.44 KiB 0 B (0.00%) 168.27 KiB 52.33 KiB ▁▁▁▁▁▁▁▁███
react-start.minimal 101.92 KiB 0 B (0.00%) 322.84 KiB 88.06 KiB ▁▁▁▁▁▁▁▁███
react-start.full 105.34 KiB 0 B (0.00%) 333.17 KiB 90.98 KiB ████████▁▁▁
react-start.rsbuild.minimal 101.45 KiB 0 B (0.00%) 325.78 KiB 87.12 KiB ▁▁▁▁▁▁▁▁███
react-start.rsbuild.full 104.76 KiB 0 B (0.00%) 336.47 KiB 89.88 KiB ▁▁▁▁▁▁▁▁███
solid-start.minimal 49.55 KiB 0 B (0.00%) 152.77 KiB 43.68 KiB ▁▁▁▁████▂▂▂
solid-start.full 55.33 KiB 0 B (0.00%) 169.68 KiB 48.71 KiB ▁▁▁▁▃███▅▅▅

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

@guru-irl guru-irl marked this pull request as draft April 29, 2026 12:49
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/router-generator/tests/generator.test.ts (1)

124-126: Add one combo fixture to lock the disableTypes no-op contract.

Consider adding a dedicated folder/case for isolatedDeclarations: true + disableTypes: true so this behavior is snapshot-guarded going forward.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-generator/tests/generator.test.ts` around lines 124 - 126,
Add a new combo fixture/case that sets both config.isolatedDeclarations = true
and config.disableTypes = true so the no-op contract for disableTypes is
snapshot-guarded; create a dedicated test folder/case name (e.g.,
"isolated-declarations-disable-types") in the generator fixtures and ensure the
test runner picks it up and a snapshot is committed to lock current behavior for
the combination, referencing the config object and the existing
'isolated-declarations' case handling to mirror how other combos are added.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/router-generator/tests/generator.test.ts`:
- Around line 124-126: Add a new combo fixture/case that sets both
config.isolatedDeclarations = true and config.disableTypes = true so the no-op
contract for disableTypes is snapshot-guarded; create a dedicated test
folder/case name (e.g., "isolated-declarations-disable-types") in the generator
fixtures and ensure the test runner picks it up and a snapshot is committed to
lock current behavior for the combination, referencing the config object and the
existing 'isolated-declarations' case handling to mirror how other combos are
added.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: decbf11b-b36c-4834-a4cc-4c988a7cfab5

📥 Commits

Reviewing files that changed from the base of the PR and between d6decca and 58b9ddf.

📒 Files selected for processing (7)
  • packages/router-generator/src/config.ts
  • packages/router-generator/src/generator.ts
  • packages/router-generator/tests/generator.test.ts
  • packages/router-generator/tests/generator/isolated-declarations/routeTree.snapshot.ts
  • packages/router-generator/tests/generator/isolated-declarations/routes/__root.tsx
  • packages/router-generator/tests/generator/isolated-declarations/routes/index.tsx
  • packages/router-generator/tests/generator/isolated-declarations/routes/posts.tsx

Gurupungav Narayanan Codespace and others added 2 commits April 29, 2026 13:44
…tants and header

Three correctness gaps in the original PR:

1. RouteWithChildren constants (generated by buildRouteTreeConfig for
   parent routes with children) were missing ': any' annotations. Add
   isolatedDeclarations param to buildRouteTreeConfig and propagate it
   through recursive calls.

2. rootRouteWithChildren (generated when the root route has component
   piece files) was also missing ': any'. Apply the same conditional.

3. The default routeTreeFileHeader includes '// @ts-nocheck', which opts
   the generated file out of type-checking entirely — defeating the
   purpose of isolatedDeclarations mode. Automatically strip
   '// @ts-nocheck' from the header when isolatedDeclarations: true.

Add 'isolated-declarations-nested' fixture to cover the WithChildren
code path (PostsRouteWithChildren: any on line 92 of snapshot).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
// @ts-nocheck is intentionally included in TanStack's default
routeTreeFileHeader. Users who need isolatedDeclarations type-checking
should configure a custom routeTreeFileHeader that omits it — that is
the right locus of control, not the generator silently overriding it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@schiller-manuel
Copy link
Copy Markdown
Contributor

This is an accepted tradeoff for projects that need isolatedDeclarations compliance

not really. this either needs to be fixed correctly or we cant support this

@guru-irl
Copy link
Copy Markdown
Author

guru-irl commented Apr 30, 2026

This is an accepted tradeoff for projects that need isolatedDeclarations compliance

not really. this either needs to be fixed correctly or we cant support this

@schiller-manuel Yep yep, this is a vibe coded draft. I'll update this with real code EOD

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