Skip to content

test: client-nav benchmarks use a more representative app#6812

Open
Sheraff wants to merge 3 commits intomainfrom
test-benchmarks-client-nav-more-representative-app
Open

test: client-nav benchmarks use a more representative app#6812
Sheraff wants to merge 3 commits intomainfrom
test-benchmarks-client-nav-more-representative-app

Conversation

@Sheraff
Copy link
Contributor

@Sheraff Sheraff commented Mar 3, 2026

make the client-nav benchmark more representative of a "full Router app" by

  • using useMatch too
  • beforeLoad, loader, loaderDeps, validateSearch route options
  • sometimes navigating the search, sometimes the params
  • add some weight to re-renders, not only re-select

Summary by CodeRabbit

Release Notes

  • Tests
    • Improved benchmark test coverage with enhanced route validation and lifecycle hooks.
    • Optimized performance benchmarks with reduced iteration cycles for faster execution.
    • Updated navigation parameter derivation to better assess rendering behavior under different update frequencies.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

Updates benchmark apps across React, Solid, and Vue frameworks to incorporate route lifecycle hooks (validateSearch, beforeLoad, loader, loaderDeps), introduce Match components using useMatch, and modify navigation cadence by deriving parameter IDs. Router configuration adds defaultPendingMinMs: 0. Performance loop iterations reduced from 100 to 50.

Changes

Cohort / File(s) Summary
App Framework Updates
benchmarks/client-nav/react/app.tsx, benchmarks/client-nav/solid/app.tsx, benchmarks/client-nav/vue/app.tsx
Added useMatch imports and new Match components; updated Params/Search components to compute and return values directly; enhanced route declarations with validateSearch, beforeLoad, loaderDeps, and loader; added defaultPendingMinMs: 0 to router config; reduced performance loop iterations from 100 to 50; added return statements to runPerfSelectorComputation.
Navigation Setup Configuration
benchmarks/client-nav/*/setup.ts
Modified id parameter calculation from nextId to Math.floor((nextId + 1) / 2) to alter navigation update cadence; added clarifying comments on parameter and search update frequency.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • TanStack/router#4993 — Touches router preload lifecycle hooks (beforeLoad/loader) and related route options that are now integrated into the benchmarks.
  • TanStack/router#6511 — Modifies route declarations around search handling with validateSearch, loaderDeps, and loader patterns used across frameworks in this PR.
  • TanStack/router#6808 — Changes client-nav benchmark navigation cadence by modifying parameter derivation logic.

Suggested labels

package: react-router, package: solid-router, package: vue-router

Suggested reviewers

  • schiller-manuel
  • nlynzaad

Poem

🐰 Hopping through frameworks with gleeful delight,
Match components and loaders working just right,
From React to Solid to Vue's verdant glow,
Route lifecycle hooks steal the performance show,
Benchmarks now balanced, our progress takes flight! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main purpose of the changeset: enhancing client-nav benchmarks to be more representative of a full Router app with new features and testing patterns.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test-benchmarks-client-nav-more-representative-app

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

@nx-cloud
Copy link

nx-cloud bot commented Mar 3, 2026

View your CI Pipeline Execution ↗ for commit 783512f

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 53s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 2s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-04 08:31:20 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 3, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@6812

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@6812

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@6812

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@6812

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@6812

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@6812

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@6812

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@6812

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@6812

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@6812

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@6812

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@6812

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@6812

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@6812

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@6812

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@6812

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@6812

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@6812

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@6812

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@6812

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@6812

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@6812

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@6812

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@6812

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@6812

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@6812

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@6812

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@6812

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@6812

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@6812

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@6812

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@6812

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@6812

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@6812

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@6812

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@6812

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@6812

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@6812

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@6812

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@6812

commit: f837402

@github-actions
Copy link

github-actions bot commented Mar 3, 2026

Bundle Size Benchmarks

  • Commit: 9f35318c41fc
  • Measured at: 2026-03-04T08:31:01.436Z
  • Baseline source: history:9f35318c41fc
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 86.58 KiB 0 B (0.00%) 272.45 KiB 75.22 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-router.full 89.61 KiB 0 B (0.00%) 282.78 KiB 77.90 KiB ▅▅▅▅▅▅▅▅▅▅▅
solid-router.minimal 35.88 KiB 0 B (0.00%) 107.56 KiB 32.26 KiB ▅▅▅▅▅▅▅▅▅▅▅
solid-router.full 40.21 KiB 0 B (0.00%) 120.61 KiB 36.13 KiB ▅▅▅▅▅▅▅▅▅▅▅
vue-router.minimal 51.75 KiB 0 B (0.00%) 147.54 KiB 46.50 KiB ▅▅▅▅▅▅▅▅▅▅▅
vue-router.full 56.55 KiB 0 B (0.00%) 163.12 KiB 50.86 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-start.minimal 99.11 KiB 0 B (0.00%) 311.58 KiB 85.68 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-start.full 102.50 KiB 0 B (0.00%) 321.39 KiB 88.63 KiB ▁██████████
solid-start.minimal 48.19 KiB 0 B (0.00%) 145.13 KiB 42.67 KiB ▅▅▅▅▅▅▅▅▅▅▅
solid-start.full 53.68 KiB 0 B (0.00%) 161.08 KiB 47.37 KiB ▁██████████

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

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11d0bd4a61

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
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 (4)
benchmarks/client-nav/vue/app.tsx (1)

100-104: Consider adding type annotations for search parameter.

Per TypeScript strict mode guidelines, the search parameter in validateSearch and loaderDeps is implicitly typed. While this works for a benchmark file, explicit typing would improve safety.

♻️ Optional: Add explicit type annotation
 const route = createRoute({
   getParentRoute: () => root,
   path: '/$id',
-  validateSearch: (search) => ({ id: search.id }),
+  validateSearch: (search: Record<string, unknown>) => ({ id: search.id as string }),
   component: () => <div />,
   beforeLoad: () => Promise.resolve(),
-  loaderDeps: ({ search }) => ({ id: search.id }),
+  loaderDeps: ({ search }: { search: { id: string } }) => ({ id: search.id }),
   loader: () => Promise.resolve(),
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@benchmarks/client-nav/vue/app.tsx` around lines 100 - 104, The validateSearch
and loaderDeps functions use an implicitly typed search parameter; add an
explicit type for search (e.g., define or import a Search type/interface) and
annotate the parameter in validateSearch (validateSearch: (search: Search) =>
...) and in loaderDeps (loaderDeps: ({ search }: { search: Search }) => ... or
equivalent destructured typing) so TypeScript strict mode is satisfied; ensure
any downstream returns ({ id: search.id }) remain unchanged and update any
related types used by loader and beforeLoad if needed to keep signatures
consistent with the new Search type.
benchmarks/client-nav/solid/speed.bench.tsx (1)

41-42: Use explicit string conversion in navigation payload to avoid implicit coercion.

For stricter typing and clearer intent, serialize both values at the callsite instead of relying on downstream coercion.

Proposed diff
       return navigate({
         to: '/$id',
-        params: { id: Math.floor((nextId + 1) / 2) },
-        search: { id: Math.floor(nextId / 2) },
+        params: { id: String(Math.floor((nextId + 1) / 2)) },
+        search: { id: String(Math.floor(nextId / 2)) },
         replace: true,
       })

As per coding guidelines: **/*.{ts,tsx}: Use TypeScript strict mode with extensive type safety.

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

In `@benchmarks/client-nav/solid/speed.bench.tsx` around lines 41 - 42, The
numeric values assigned to params and search are implicitly coerced from nextId;
update the callsite to explicitly serialize both values to strings (e.g., use
String(nextIdExpression) or .toString()) for params.id and search.id to satisfy
strict TypeScript typing and avoid implicit coercion; locate the object with
keys params and search that reference nextId and replace the numeric expressions
(Math.floor((nextId + 1) / 2) and Math.floor(nextId / 2)) with their stringified
equivalents.
benchmarks/client-nav/solid/app.tsx (1)

78-84: Normalize search.id in validateSearch to keep downstream types stable.

validateSearch currently forwards search.id as-is, so loaderDeps inherits a weakly-typed value. Normalizing once here keeps search typing deterministic across the route lifecycle.

Proposed diff
 const route = createRoute({
   getParentRoute: () => root,
   path: '/$id',
-  validateSearch: (search) => ({ id: search.id }),
+  validateSearch: (search) => ({
+    id:
+      typeof search.id === 'string'
+        ? search.id
+        : String(search.id ?? '0'),
+  }),
   component: () => {
     return <div />
   },
   beforeLoad: () => Promise.resolve(),
   loaderDeps: ({ search }) => ({ id: search.id }),
   loader: () => Promise.resolve(),
 })

As per coding guidelines: **/*.{ts,tsx}: Use TypeScript strict mode with extensive type safety.

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

In `@benchmarks/client-nav/solid/app.tsx` around lines 78 - 84, validateSearch is
forwarding search.id raw which makes downstream types in loaderDeps unstable;
update validateSearch to normalize id (e.g., return { id: String(search.id ??
'') } or another explicit normalized type your route expects) so the route
lifecycle has a deterministic type for id; change the implementation of
validateSearch (and confirm loaderDeps: ({ search }) => ({ id: search.id }) now
receives the normalized/typed id) to keep types strict and consistent across
validateSearch, loaderDeps, and loader.
benchmarks/client-nav/react/app.tsx (1)

85-89: Consider type-safe validation in benchmarks only if consistency is preferred across frameworks.

While stricter input validation for search.id would align with TypeScript's strict mode expectations, this is a performance benchmark where minimal overhead is intentional. The three framework implementations (React, Solid, Vue) all use identical pass-through validation, and the actual performance-sensitive code in the component already normalizes the value where it matters (line 37: Number(search.id ?? 0)). The loaders and component handlers are no-ops, so the validation doesn't affect benchmark accuracy. Adopt the suggested normalization only if cross-framework consistency or downstream type contracts require stricter schemas.

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

In `@benchmarks/client-nav/react/app.tsx` around lines 85 - 89, The current
pass-through validation in validateSearch and loaderDeps yields ({ id: search.id
}) which is intentional for minimal overhead in benchmarks; if you decide to
enforce type-safe normalization for cross-framework consistency, update
validateSearch and loaderDeps to normalize id (e.g., convert to a number with
Number(search.id ?? 0)) so downstream code (including component and loader)
receives a predictable numeric id, and adjust any related loader or loaderDeps
expectations accordingly; otherwise leave the existing pass-through
implementations (validateSearch, loaderDeps, component, loader) as-is to avoid
adding benchmark overhead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@benchmarks/client-nav/react/app.tsx`:
- Around line 85-89: The current pass-through validation in validateSearch and
loaderDeps yields ({ id: search.id }) which is intentional for minimal overhead
in benchmarks; if you decide to enforce type-safe normalization for
cross-framework consistency, update validateSearch and loaderDeps to normalize
id (e.g., convert to a number with Number(search.id ?? 0)) so downstream code
(including component and loader) receives a predictable numeric id, and adjust
any related loader or loaderDeps expectations accordingly; otherwise leave the
existing pass-through implementations (validateSearch, loaderDeps, component,
loader) as-is to avoid adding benchmark overhead.

In `@benchmarks/client-nav/solid/app.tsx`:
- Around line 78-84: validateSearch is forwarding search.id raw which makes
downstream types in loaderDeps unstable; update validateSearch to normalize id
(e.g., return { id: String(search.id ?? '') } or another explicit normalized
type your route expects) so the route lifecycle has a deterministic type for id;
change the implementation of validateSearch (and confirm loaderDeps: ({ search
}) => ({ id: search.id }) now receives the normalized/typed id) to keep types
strict and consistent across validateSearch, loaderDeps, and loader.

In `@benchmarks/client-nav/solid/speed.bench.tsx`:
- Around line 41-42: The numeric values assigned to params and search are
implicitly coerced from nextId; update the callsite to explicitly serialize both
values to strings (e.g., use String(nextIdExpression) or .toString()) for
params.id and search.id to satisfy strict TypeScript typing and avoid implicit
coercion; locate the object with keys params and search that reference nextId
and replace the numeric expressions (Math.floor((nextId + 1) / 2) and
Math.floor(nextId / 2)) with their stringified equivalents.

In `@benchmarks/client-nav/vue/app.tsx`:
- Around line 100-104: The validateSearch and loaderDeps functions use an
implicitly typed search parameter; add an explicit type for search (e.g., define
or import a Search type/interface) and annotate the parameter in validateSearch
(validateSearch: (search: Search) => ...) and in loaderDeps (loaderDeps: ({
search }: { search: Search }) => ... or equivalent destructured typing) so
TypeScript strict mode is satisfied; ensure any downstream returns ({ id:
search.id }) remain unchanged and update any related types used by loader and
beforeLoad if needed to keep signatures consistent with the new Search type.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2217f7c and 11d0bd4.

📒 Files selected for processing (6)
  • benchmarks/client-nav/react/app.tsx
  • benchmarks/client-nav/react/speed.bench.tsx
  • benchmarks/client-nav/solid/app.tsx
  • benchmarks/client-nav/solid/speed.bench.tsx
  • benchmarks/client-nav/vue/app.tsx
  • benchmarks/client-nav/vue/speed.bench.tsx

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 3, 2026

Merging this PR will degrade performance by 18.98%

❌ 1 regressed benchmark
✅ 4 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
client-side navigation loop (vue) 64.8 ms 80 ms -18.98%

Comparing test-benchmarks-client-nav-more-representative-app (783512f) with main (9f35318)

Open in CodSpeed

Copy link
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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
benchmarks/client-nav/solid/app.tsx (1)

78-78: Type safety: validateSearch accesses search.id without type narrowing.

The search parameter in validateSearch is Record<string, unknown> by default. Accessing search.id directly may cause TypeScript errors in strict mode since the value is unknown. Consider adding type assertion or proper validation.

✏️ Proposed fix with type assertion
-  validateSearch: (search) => ({ id: search.id }),
+  validateSearch: (search: Record<string, unknown>) => ({ id: search.id as string }),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@benchmarks/client-nav/solid/app.tsx` at line 78, The validateSearch
implementation uses search.id on a parameter typed as Record<string, unknown>,
causing TypeScript errors; update validateSearch (the function named
validateSearch) to narrow or assert the type of search before accessing .id —
either add a runtime guard that checks search is an object and that 'id' in
search and typeof (search['id']) === 'string' (or the expected type) before
returning { id: ... }, or change the function signature to accept a properly
typed parameter (e.g., { id: string } or a typed interface) and adjust callers
accordingly so access to search.id is type-safe.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@benchmarks/client-nav/solid/app.tsx`:
- Around line 43-49: The select callback in Match is accessing match.params.id
but with strict: false match.params can be undefined; update the select to use
optional chaining (e.g. select: (match) =>
runPerfSelectorComputation(Number(match.params?.id ?? 0))) so params is safely
accessed, and ensure any other direct uses of match.params in Match use the same
match.params?.id pattern; keep using runPerfSelectorComputation and the number()
call as-is.

---

Nitpick comments:
In `@benchmarks/client-nav/solid/app.tsx`:
- Line 78: The validateSearch implementation uses search.id on a parameter typed
as Record<string, unknown>, causing TypeScript errors; update validateSearch
(the function named validateSearch) to narrow or assert the type of search
before accessing .id — either add a runtime guard that checks search is an
object and that 'id' in search and typeof (search['id']) === 'string' (or the
expected type) before returning { id: ... }, or change the function signature to
accept a properly typed parameter (e.g., { id: string } or a typed interface)
and adjust callers accordingly so access to search.id is type-safe.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 11d0bd4 and 016e842.

📒 Files selected for processing (1)
  • benchmarks/client-nav/solid/app.tsx

Comment on lines +43 to 49
function Match() {
const number = useMatch({
strict: false,
select: (match) => runPerfSelectorComputation(Number(match.params.id ?? 0)),
})

return null
return <>{runPerfSelectorComputation(number())}</>
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n benchmarks/client-nav/solid/app.tsx | head -60

Repository: TanStack/router

Length of output: 1748


🌐 Web query:

TanStack Router useMatch strict false select callback documentation

💡 Result:

TanStack Router documents useMatch’s strict and select options on the useMatch hook API page. (tanstack.com)

strict: false

  • Default is true.
  • If strict is false, you must not pass from (it must be unset), and the returned match type is loosened (a Partial<RouteMatch>-style shape) to reflect that it could be any active match. (tanstack.com)
  • This is intended for shared/reusable components where you don’t know which route you’re under (also described in the Type Safety guide). (tanstack.com)

Example:

const match = useMatch({ strict: false })

(tanstack.com)

select: (match) => TSelected (the “select callback”)

  • Optional function called with the RouteMatch.
  • useMatch returns whatever your select returns.
  • The selected value is also used to decide whether to re-render (via shallow equality checks). (tanstack.com)

Example:

const pathname = useMatch({
  strict: false,
  select: (match) => match.pathname,
})

(Example pattern referenced in community discussion; core behavior is in the docs.) (tanstack.com)

Citations:


🏁 Script executed:

rg "strict.*false" benchmarks/client-nav/solid/app.tsx -A 3

Repository: TanStack/router

Length of output: 528


🌐 Web query:

TanStack Solid Router useMatch RouteMatch Partial type strict false

💡 Result:

In TanStack Router for Solid (@tanstack/solid-router), this is expected behavior:

  • useMatch is strict by default (strict: true). In strict mode you should pass from (a route id/path), and you get a fully-typed RouteMatch. (tanstack.com)
  • If you set strict: false, you must NOT pass from, and the return type becomes Partial<RouteMatch> (so properties like search are optional / possibly undefined). This is by design for reusable/shared components. (tanstack.com)

What to do

1) Route-specific component (fully typed)

const match = useMatch({ from: Route.fullPath }) // or Route.id
// match.search is fully typed

(tanstack.com)

2) Reusable component across many routes (no invariant, looser types)

const match = useMatch({ strict: false })
// match is Partial<RouteMatch>, so match.search may be undefined

(tanstack.com)

3) If you don’t want it to throw when a specific match isn’t active

const match = useMatch({ from: '/posts', shouldThrow: false }) // RouteMatch | undefined

(tanstack.com)

Citations:


🏁 Script executed:

# Search for type definitions or documentation in the repo
fd -e ts -e tsx | xargs rg "Partial.*RouteMatch" | head -20

Repository: TanStack/router

Length of output: 41


🏁 Script executed:

# Check for tsconfig and strict mode settings
fd -e json -name "tsconfig*" | xargs cat | grep -A 10 '"strict"' || echo "No strict setting found"

Repository: TanStack/router

Length of output: 330


🏁 Script executed:

# Check for any type errors or eslint configs
fd -e json -name ".eslintrc*" -o -name "tsconfig*" benchmarks/ | head -5

Repository: TanStack/router

Length of output: 289


🏁 Script executed:

# Look for type definition or implementation of useMatch in solid-router
fd "@tanstack/solid-router" -t d | head -3

Repository: TanStack/router

Length of output: 41


🏁 Script executed:

find . -name "tsconfig*.json" -type f 2>/dev/null | head -10

Repository: TanStack/router

Length of output: 435


🏁 Script executed:

# Look for TypeScript configuration
cat tsconfig.json 2>/dev/null | head -30 || echo "No root tsconfig found"

Repository: TanStack/router

Length of output: 846


🏁 Script executed:

# Check if there's a type definition file in node_modules or packages
find . -path "*/node_modules/@tanstack/solid-router*" -name "*.d.ts" 2>/dev/null | head -5 || echo "Type definitions not found in sandbox"

Repository: TanStack/router

Length of output: 41


🏁 Script executed:

# Search for type definitions within the repo itself
find . -path "*/packages/solid-router*" -type f \( -name "*.ts" -o -name "*.tsx" \) | grep -i "use-match\|useMatch" | head -10

Repository: TanStack/router

Length of output: 197


🏁 Script executed:

cat benchmarks/client-nav/solid/tsconfig.json

Repository: TanStack/router

Length of output: 315


🏁 Script executed:

cat packages/solid-router/src/useMatch.tsx

Repository: TanStack/router

Length of output: 3495


Use optional chaining to safely access match.params with strict: false.

With strict: false, the useMatch hook types the match parameter in the select callback as a partial/union type (MakeRouteMatchUnion), making the params property optional. Accessing match.params.id directly will fail TypeScript strict mode type checking. Use optional chaining to safely handle the potentially undefined params property:

 function Match() {
   const number = useMatch({
     strict: false,
-    select: (match) => runPerfSelectorComputation(Number(match.params.id ?? 0)),
+    select: (match) => runPerfSelectorComputation(Number(match?.params?.id ?? 0)),
   })
   return <>{runPerfSelectorComputation(number())}</>
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function Match() {
const number = useMatch({
strict: false,
select: (match) => runPerfSelectorComputation(Number(match.params.id ?? 0)),
})
return null
return <>{runPerfSelectorComputation(number())}</>
}
function Match() {
const number = useMatch({
strict: false,
select: (match) => runPerfSelectorComputation(Number(match?.params?.id ?? 0)),
})
return <>{runPerfSelectorComputation(number())}</>
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@benchmarks/client-nav/solid/app.tsx` around lines 43 - 49, The select
callback in Match is accessing match.params.id but with strict: false
match.params can be undefined; update the select to use optional chaining (e.g.
select: (match) => runPerfSelectorComputation(Number(match.params?.id ?? 0))) so
params is safely accessed, and ensure any other direct uses of match.params in
Match use the same match.params?.id pattern; keep using
runPerfSelectorComputation and the number() call as-is.

Copy link
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.

Actionable comments posted: 2

♻️ Duplicate comments (1)
benchmarks/client-nav/solid/app.tsx (1)

43-47: ⚠️ Potential issue | 🟡 Minor

Guard match.params access in Match (Line 46).

This still directly dereferences match.params.id while using strict: false. Please make it null-safe to satisfy strict type-safety expectations.

Suggested patch
 function Match() {
   const number = useMatch({
     strict: false,
-    select: (match) => runPerfSelectorComputation(Number(match.params.id ?? 0)),
+    select: (match) =>
+      runPerfSelectorComputation(Number(match.params?.id ?? 0)),
   })
   return <>{runPerfSelectorComputation(number())}</>
 }
In `@tanstack/solid-router`, when useMatch is called with `strict: false` (and no `from`), is `params` guaranteed to exist in the `select` callback type, or should it be treated as optional?

As per coding guidelines: **/*.{ts,tsx}: Use TypeScript strict mode with extensive type safety.

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

In `@benchmarks/client-nav/solid/app.tsx` around lines 43 - 47, In Match's
useMatch select callback, guard against match.params being undefined before
dereferencing id: update the select handler passed to useMatch (in the Match
function) so it safely reads match?.params?.id (or checks match && match.params)
and falls back to 0 when absent, then pass Number(...) into
runPerfSelectorComputation; ensure this null-safe access is used since useMatch
is called with strict: false.
🧹 Nitpick comments (1)
benchmarks/client-nav/react/app.tsx (1)

85-89: Add type annotation and normalization to validateSearch for strict type safety.

Line 85 currently forwards raw search.id without validation. TanStack Router's recommended pattern is to treat validateSearch as a normalization step—apply type conversions (e.g., ensuring string values have a fallback), and match the shape used downstream in loaderDeps (line 88). This ensures the typed shape is guaranteed at the boundary rather than relying on runtime assumptions.

♻️ Proposed type-safe normalization
 const route = createRoute({
   getParentRoute: () => root,
   path: '/$id',
-  validateSearch: (search) => ({ id: search.id }),
+  validateSearch: (search: Record<string, unknown>) => {
+    const id = typeof search.id === 'string' ? search.id : '0'
+    return { id }
+  },
   component: () => <div />,
   beforeLoad: () => Promise.resolve(),
   loaderDeps: ({ search }) => ({ id: search.id }),
   loader: () => Promise.resolve(),
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@benchmarks/client-nav/react/app.tsx` around lines 85 - 89, validateSearch
currently returns raw search.id with no typing or normalization; update the
validateSearch function to accept a typed parameter (e.g., the search/query
shape) and return a normalized and typed object matching loaderDeps (same keys
as loaderDeps: id), applying conversions/fallbacks (e.g., coerce to string,
provide default when undefined/null, or parse numbers if expected) so callers
receive a guaranteed shape; locate validateSearch and loaderDeps in the route
config and ensure their return types align (same interface/type) and add the
normalization logic to validateSearch to enforce the shape used downstream.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@benchmarks/client-nav/react/app.tsx`:
- Around line 42-47: The Match component is using useMatch without binding to
the route that contains the id param, so match.params.id is always undefined;
update the useMatch call in Match() to include the from option pointing to the
'/$id' route (e.g., useMatch({ from: '/$id', strict: false, select: ... })) so
it resolves the correct route params before passing Number(match.params.id ?? 0)
into runPerfSelectorComputation.

In `@benchmarks/client-nav/vue/app.tsx`:
- Around line 100-104: The validateSearch function lacks an explicit parameter
type and must narrow the id for strict mode; update validateSearch's signature
to annotate its parameter (e.g., validateSearch: (search: { id?: unknown }) =>
...) and perform a runtime narrowing/validation of search.id (e.g., check typeof
search.id === 'string' or another expected type and throw or return a default if
invalid) before returning { id: search.id } so the returned id has a concrete
type; mirror the same explicit typing/narrowing approach for loaderDeps: ({
search }) => ({ id: search.id }) so both validateSearch and loaderDeps use the
same declared search shape and well-typed id.

---

Duplicate comments:
In `@benchmarks/client-nav/solid/app.tsx`:
- Around line 43-47: In Match's useMatch select callback, guard against
match.params being undefined before dereferencing id: update the select handler
passed to useMatch (in the Match function) so it safely reads match?.params?.id
(or checks match && match.params) and falls back to 0 when absent, then pass
Number(...) into runPerfSelectorComputation; ensure this null-safe access is
used since useMatch is called with strict: false.

---

Nitpick comments:
In `@benchmarks/client-nav/react/app.tsx`:
- Around line 85-89: validateSearch currently returns raw search.id with no
typing or normalization; update the validateSearch function to accept a typed
parameter (e.g., the search/query shape) and return a normalized and typed
object matching loaderDeps (same keys as loaderDeps: id), applying
conversions/fallbacks (e.g., coerce to string, provide default when
undefined/null, or parse numbers if expected) so callers receive a guaranteed
shape; locate validateSearch and loaderDeps in the route config and ensure their
return types align (same interface/type) and add the normalization logic to
validateSearch to enforce the shape used downstream.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba327672-dd12-4463-bf27-e7a12f22030f

📥 Commits

Reviewing files that changed from the base of the PR and between 016e842 and 783512f.

📒 Files selected for processing (6)
  • benchmarks/client-nav/react/app.tsx
  • benchmarks/client-nav/react/setup.ts
  • benchmarks/client-nav/solid/app.tsx
  • benchmarks/client-nav/solid/setup.ts
  • benchmarks/client-nav/vue/app.tsx
  • benchmarks/client-nav/vue/setup.ts

Comment on lines +42 to +47
function Match() {
const number = useMatch({
strict: false,
select: (match) => runPerfSelectorComputation(Number(match.params.id ?? 0)),
})
return runPerfSelectorComputation(number)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# First, understand the complete structure of the benchmark file
echo "=== BENCHMARK FILE STRUCTURE ==="
wc -l benchmarks/client-nav/react/app.tsx

Repository: TanStack/router

Length of output: 131


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Get the full file to understand route structure and Match usage
echo "=== FULL BENCHMARK FILE ==="
cat -n benchmarks/client-nav/react/app.tsx

Repository: TanStack/router

Length of output: 3066


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find useMatch implementation and its behavior
echo "=== USEWATCH IMPLEMENTATION ==="
find . -type f \( -name "*.ts" -o -name "*.tsx" \) | xargs grep -l "export.*useMatch\|export const useMatch" | head -5

Repository: TanStack/router

Length of output: 289


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for useMatch in the main source code
rg -nP 'export.*function useMatch|export const useMatch' --type=ts --type=tsx

Repository: TanStack/router

Length of output: 86


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Get useMatch implementation
echo "=== USEWATCH IMPLEMENTATION ==="
cat -n packages/react-router/src/useMatch.tsx

Repository: TanStack/router

Length of output: 4193


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for how useMatch resolves when from is not specified
rg -nP 'matchContext|nearestMatchId|from.*:' packages/react-router/src/useMatch.tsx -A5 -B2

Repository: TanStack/router

Length of output: 1035


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check what strict: false does in useMatch
rg -nP 'strict.*false|strict.*true|strict\s*:' packages/react-router/src/useMatch.tsx -B3 -A3

Repository: TanStack/router

Length of output: 41


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look at useSearch and useParams to understand the pattern
echo "=== COMPARISON: useParams IMPLEMENTATION ==="
rg -nP 'export function useParams|export const useParams' -A30 packages/react-router/src/ --type ts --type tsx | head -50

Repository: TanStack/router

Length of output: 148


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check matchContext to understand what nearestMatchId represents
cat -n packages/react-router/src/matchContext.tsx

Repository: TanStack/router

Length of output: 434


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify useParams implementation to compare patterns
cat -n packages/react-router/src/useParams.tsx | head -100

Repository: TanStack/router

Length of output: 3445


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check how Root component would be rendered and what match context it would have
# Also verify the route structure initialization
cat -n benchmarks/client-nav/react/app.tsx | grep -A50 "const root\|const route\|createRouter"

Repository: TanStack/router

Length of output: 2385


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for where matchContext is set/provided in the router
rg -nP 'matchContext\.Provider|matchContext.*value' packages/react-router/src/ -B2 -A2

Repository: TanStack/router

Length of output: 1446


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check the Match component to see how matchContext is set
cat -n packages/react-router/src/Match.tsx | head -100

Repository: TanStack/router

Length of output: 4209


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify the root route setup - does it have params?
rg -nP 'createRootRoute|path.*root' benchmarks/client-nav/react/app.tsx -B2 -A5

Repository: TanStack/router

Length of output: 347


Bind useMatch to the /$id route to access its parameters.

The Match() component is rendered inside the root route's match context. When useMatch({ strict: false }) is called without a from option, it resolves to the nearest match—the root route—which has no id parameter. This causes match.params.id to always be undefined, falling back to 0, which doesn't reflect actual navigation state and reduces performance variation in this benchmark.

Suggested fix
 function Match() {
   const number = useMatch({
-    strict: false,
-    select: (match) => runPerfSelectorComputation(Number(match.params.id ?? 0)),
+    from: '/$id',
+    shouldThrow: false,
+    select: (match) => runPerfSelectorComputation(Number(match?.params.id ?? 0)),
   })
   return runPerfSelectorComputation(number)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function Match() {
const number = useMatch({
strict: false,
select: (match) => runPerfSelectorComputation(Number(match.params.id ?? 0)),
})
return runPerfSelectorComputation(number)
function Match() {
const number = useMatch({
from: '/$id',
shouldThrow: false,
select: (match) => runPerfSelectorComputation(Number(match?.params.id ?? 0)),
})
return runPerfSelectorComputation(number)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@benchmarks/client-nav/react/app.tsx` around lines 42 - 47, The Match
component is using useMatch without binding to the route that contains the id
param, so match.params.id is always undefined; update the useMatch call in
Match() to include the from option pointing to the '/$id' route (e.g.,
useMatch({ from: '/$id', strict: false, select: ... })) so it resolves the
correct route params before passing Number(match.params.id ?? 0) into
runPerfSelectorComputation.

Comment on lines +100 to +104
validateSearch: (search) => ({ id: search.id }),
component: () => <div />,
beforeLoad: () => Promise.resolve(),
loaderDeps: ({ search }) => ({ id: search.id }),
loader: () => Promise.resolve(),
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check if file exists and examine the code =="
if [ -f benchmarks/client-nav/vue/app.tsx ]; then
  echo "File exists. Showing lines 95-110:"
  sed -n '95,110p' benchmarks/client-nav/vue/app.tsx
else
  echo "File not found at benchmarks/client-nav/vue/app.tsx"
fi

echo
echo "== List files in benchmarks/client-nav =="
fd . benchmarks/client-nav --max-depth 2 -t f | head -20

Repository: TanStack/router

Length of output: 1372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check TypeScript strict mode settings =="
find . -name "tsconfig.json" -type f | head -10 | while read f; do
  echo "--- $f ---"
  jq '.compilerOptions | {strict, noImplicitAny, noImplicitThis}' "$f" 2>/dev/null || cat "$f"
done

Repository: TanStack/router

Length of output: 1281


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for validateSearch patterns =="
rg -n "validateSearch" benchmarks --type tsx --type ts -A 2 | head -50

Repository: TanStack/router

Length of output: 144


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check root and parent tsconfigs =="
for f in ./tsconfig.json ./tsconfig.base.json ./benchmarks/tsconfig.json benchmarks/client-nav/tsconfig.json benchmarks/client-nav/vue/tsconfig.json; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    head -30 "$f"
    echo
  fi
done

echo "== Check if benchmarks/client-nav/vue/tsconfig.json extends anything =="
cat benchmarks/client-nav/vue/tsconfig.json

Repository: TanStack/router

Length of output: 1959


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for validateSearch in tsx files =="
rg -n "validateSearch" benchmarks/client-nav --type-list | head
rg -n "validateSearch" benchmarks/client-nav -t ts -t tsx 2>/dev/null | head -20 || find benchmarks/client-nav -name "*.tsx" -exec rg -n "validateSearch" {} +

Repository: TanStack/router

Length of output: 510


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check what the search parameter type is =="
sed -n '1,110p' benchmarks/client-nav/vue/app.tsx | tail -50

Repository: TanStack/router

Length of output: 1258


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Find createRoute definition and validateSearch typing =="
find . -path ./node_modules -prune -o -name "*.ts" -o -name "*.tsx" | xargs rg -l "createRoute" | grep -E "(src|packages)" | head -5

echo
echo "== Search for other validateSearch usages in non-benchmark code =="
rg -n "validateSearch" src packages --type ts --type tsx -B 1 -A 1 2>/dev/null | head -60 || find . -path ./node_modules -prune -o -path ./benchmarks -prune -o \( -name "*.ts" -o -name "*.tsx" \) -exec rg -l "validateSearch" {} +

Repository: TanStack/router

Length of output: 367


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check actual React benchmark for comparison =="
if [ -f benchmarks/client-nav/react/app.tsx ]; then
  echo "=== React benchmark validateSearch ==="
  rg -n "validateSearch" benchmarks/client-nav/react/app.tsx -B 2 -A 2
fi

echo
echo "== Check if there are type definitions or examples for validateSearch =="
rg -n "validateSearch.*search\|search.*validateSearch" packages src e2e --type ts --type tsx -A 3 2>/dev/null | head -80 || find . -path ./node_modules -prune -o \( -name "*.ts" -o -name "*.tsx" \) -exec rg "validateSearch" {} + | grep -v benchmarks | head -20

Repository: TanStack/router

Length of output: 3321


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Look at the e2e example that uses explicit typing =="
if [ -f e2e/vue-router/basic-file-based-jsx/src/routes/remountDeps.tsx ]; then
  rg -n "validateSearch" e2e/vue-router/basic-file-based-jsx/src/routes/remountDeps.tsx -B 2 -A 5
fi

echo
echo "== Check if TypeScript compilation would fail for the benchmark =="
echo "Looking for any build or type-check scripts..."
cat benchmarks/client-nav/package.json | grep -A 20 '"scripts"' || echo "No package.json found"

Repository: TanStack/router

Length of output: 2040


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check if benchmarks are included in any type-checking or build =="
cat package.json | jq '.scripts' | head -30
echo
echo "== Look at what README says about benchmarks =="
head -50 benchmarks/client-nav/README.md

Repository: TanStack/router

Length of output: 3999


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Verify the exact pattern used in e2e tests =="
cat e2e/vue-router/basic-file-based-jsx/src/routes/remountDeps.tsx | sed -n '1,80p'

Repository: TanStack/router

Length of output: 548


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check what happens when running type check on benchmarks =="
echo "Trying to type-check the vue benchmark..."
tsc -p benchmarks/client-nav/vue/tsconfig.json --noEmit 2>&1 | head -30 || true

echo
echo "== Check if the pattern in the code is correct given the input =="
echo "What type does TypeScript infer for validateSearch parameter?"
cat > /tmp/check.ts << 'EOF'
import { createRoute } from '@tanstack/router'

// Checking the implicit type of search parameter
const route = createRoute({
  path: '/$id',
  validateSearch: (search) => ({ id: search.id }),
})
EOF

tsc --noEmit --strict /tmp/check.ts 2>&1 | head -20 || echo "Type check completed"

Repository: TanStack/router

Length of output: 691


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check if React benchmark has the same issue =="
rg -n "validateSearch" benchmarks/client-nav/react/app.tsx -B 1 -A 1

echo
echo "== Do both benchmarks have identical validateSearch patterns? =="
echo "Vue:"
rg -n "validateSearch:" benchmarks/client-nav/vue/app.tsx -A 1
echo
echo "React:"
rg -n "validateSearch:" benchmarks/client-nav/react/app.tsx -A 1

Repository: TanStack/router

Length of output: 463


Add explicit type annotation and narrowing to validateSearch for strict mode compliance.

The search parameter lacks explicit typing, which causes an implicit any type under strict mode. Align with e2e test patterns by annotating the parameter and narrowing the id value.

Suggested refactor
 const route = createRoute({
   getParentRoute: () => root,
   path: '/$id',
-  validateSearch: (search) => ({ id: search.id }),
+  validateSearch: (search: Record<string, unknown>) => ({
+    id: typeof search.id === 'string' ? search.id : '0',
+  }),
   component: () => <div />,
   beforeLoad: () => Promise.resolve(),
   loaderDeps: ({ search }) => ({ id: search.id }),
   loader: () => Promise.resolve(),
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
validateSearch: (search) => ({ id: search.id }),
component: () => <div />,
beforeLoad: () => Promise.resolve(),
loaderDeps: ({ search }) => ({ id: search.id }),
loader: () => Promise.resolve(),
validateSearch: (search: Record<string, unknown>) => ({
id: typeof search.id === 'string' ? search.id : '0',
}),
component: () => <div />,
beforeLoad: () => Promise.resolve(),
loaderDeps: ({ search }) => ({ id: search.id }),
loader: () => Promise.resolve(),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@benchmarks/client-nav/vue/app.tsx` around lines 100 - 104, The validateSearch
function lacks an explicit parameter type and must narrow the id for strict
mode; update validateSearch's signature to annotate its parameter (e.g.,
validateSearch: (search: { id?: unknown }) => ...) and perform a runtime
narrowing/validation of search.id (e.g., check typeof search.id === 'string' or
another expected type and throw or return a default if invalid) before returning
{ id: search.id } so the returned id has a concrete type; mirror the same
explicit typing/narrowing approach for loaderDeps: ({ search }) => ({ id:
search.id }) so both validateSearch and loaderDeps use the same declared search
shape and well-typed id.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant