Replies: 1 comment
-
|
can you please provide a complete reproducer project that exhibits this behavior? |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
NOTE: I've been working with a ~5 person team and suggested Tanstack Start. It's been a fantastic DX so far, and I'm very glad we chose this as our framework. However, we've recently hit a hard limit where TS seems incapable of type checking our web app. My theory is simply that the types for RouteTree are so significant, that it always OOM errors. I also attempted to use
tsgoto see if it would help speed up the type checking, but it similarly fails. I'm at a loss on how to proceed aside from removing type checking from the web app entirely. Any suggestions or assistance would be greatly appreciated! (Claude auto-generated the content below, but I'm happy to set up a more thorough example if that'd be helpful.)GitHub Issue Draft: TypeScript Performance with Large Route Trees
Repo: TanStack/router
Title: TypeScript performance degrades severely with 379+ routes (~15M type instantiations, incompatible with tsgo)
Which project does this relate to?
Router / Start
Describe the bug
TypeScript performance degrades severely in applications with large route trees. Our production app with 379 registered routes experiences:
tsc --noEmitcheck withincremental: falsetsc --noEmitcheck withincremental: true(~28s checking + 39+ minutes serializing the.tsbuildinfofile for 15.4M instantiations)tsgo(TypeScript Native Preview /@typescript/native-preview)tsc --diagnosticsNODE_OPTIONS=--max-old-space-size=8192) — default heap OOMsThe generated
routeTree.gen.tsis 8,898 lines with 379 route imports, nested child interfaces, and massive union types inFileRouteTypes. Even thoughrouteTree.gen.tsitself is excluded from typechecking via// @ts-nocheck, its types are consumed transitively throughrouter.tsx→routeTree.gen→Registermodule augmentation.Why this matters
tsgo incompatibility: TypeScript Native Preview (
tsgo) is the future of TypeScript, offering 5-68x speedups on normal codebases. TanStack Router's type complexity makes it completely unusable — it explodes to 22+ GB RAM and never completes. This blocks adoption oftsgofor any project using TanStack Router with a non-trivial route count.CI/CD impact: A 10-minute typecheck for a single app (on top of fast package checks) is a significant bottleneck. With
incremental: true, cold checks balloon to 40+ minutes due to buildinfo serialization overhead.Developer experience: New clones, CI runners, and cache-busted environments all hit the pathological cold-check path. The 8 GB heap requirement is unusual and can cause mysterious OOMs in constrained environments.
Your Example Website or App
Not a public repo (production SaaS), but the structure is reproducible.
Steps to Reproduce the Bug or Issue
tsc --noEmit --diagnosticstsgo --noEmit— observe 22+ GB memory usage before OOMOur route structure
Generated
routeTree.gen.tsstructure (8,898 lines)The key issue is that every file that imports from
@tanstack/react-router(e.g.,useParams,useSearch,Link,useNavigate) triggers a lookup into theRegisterinterface, which forces TypeScript to fully resolve the entire 379-routeFileRouteTypes— including all the nested child interfaces, union types, and object type maps.router.tsxmodule augmentation (also triggers full resolution)Expected behavior
tsgo(TypeScript Native Preview)tsc --diagnosticsoutput (non-incremental, cold)With
incremental: false, the cold check takes ~28 seconds — entirely reasonable. However, withincremental: true(the default inherited from our base tsconfig), cold checks balloon to 40+ minutes because serializing the.tsbuildinfofile for 15.4M instantiations is pathologically slow. This means the first typecheck after any cache bust is brutally expensive.The 15.4 million type instantiations for a 379-route app is the core issue. For comparison, our 17 other packages (same monorepo, no TanStack Router) produce ~50K instantiations combined.
Platform
^1.161.1^1.161.15.8.3@typescript/native-preview@7.0.0-dev.20250218.1(OOMs)Suggestions
Some potential approaches that could help:
Lazy type resolution: Instead of eagerly resolving all 379 routes when
Registeris accessed, use conditional/deferred types that only resolve the specific route being used (e.g., whenuseParamsis called in a specific route file, only resolve that route's types).Route tree type chunking: Split
FileRouteTypesinto smaller per-layout-group types that are composed lazily rather than as one massive union.Simplified
Registerinterface: TheAwaited<ReturnType<typeof getRouter>>in the module augmentation forces full inference of the entire router creation. A simpler type reference (perhaps a pre-computed type literal) could avoid this.tsgo compatibility testing: Adding
tsgoto the CI matrix would catch regressions before they ship. The TypeScript team is actively working ontsgoand route-heavy apps are a perfect stress test.Type complexity budget: Consider a maximum route count or type depth budget with a documented escape hatch for large apps.
Additional context
tsgosuccessfully — they typecheck in 2.5 seconds total. The web app with TanStack Router is the sole holdout.routeTree.gen.tsfile itself is correctly excluded from typechecking via// @ts-nocheck, but the types are consumed transitively through imports.Beta Was this translation helpful? Give feedback.
All reactions