Fix circular TypeScript type error when arrow function route components access matches#15163
Open
Zelys-DFKH wants to merge 1 commit into
Open
Conversation
…ts access matches
Arrow function route components that destructure `matches` from
`Route.ComponentProps` get a circular type error. The generated
`Matches` tuple contained `{ module: typeof import('./self') }` for the
current route's entry. TypeScript's `RouteModule` assignability check
evaluates `["default"]`, which for arrow functions requires resolving the
parameter type annotation — looping back to `Route.ComponentProps`.
Fix: typegen now emits `{ id, loaderData: Info["loaderData"] }` for the
self-entry instead of `{ id, module: typeof import('./self') }`.
`Info["loaderData"]` is computed via `GetLoaderData`, which only accesses
`["loader"]` and `["clientLoader"]`, not `["default"]`, so the cycle
never forms. This required adding `MatchInfoWithLoaderData` (with
`module?: never` for a disjoint discriminant) alongside `MatchInfo`, plus
corresponding updates to `Match<T>`, `Matches<T>`, `MetaMatch<T>`, and
`MetaMatches<T>` to accept `AnyMatchInfo`.
Fixes remix-run#12499
Contributor
✅ Change File FoundA change file file exists in this PR. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #12499 — TypeScript error when accessing
matchesin an arrow function route component.What
Arrow function route components that destructure
matchesfromRoute.ComponentPropsget a TypeScript circular type error. The same annotation on a function declaration works fine.Why it fails
The generated
+types/*.tsbuilds aMatchestuple where the current route's entry is{ id, module: typeof import("./self") }. When TypeScript resolvesComponentProps["matches"], it verifies themodulefield is assignable toRouteModule. That check evaluates["default"]— the route component itself. For arrow functions, TypeScript needs to evaluate the parameter type annotation to determine the function's type, which requires resolvingRoute.ComponentProps, forming a cycle.Function declarations skip it because TypeScript reads their signature from the declaration without evaluating parameter types.
Fix
For the current route's entry in the
Matchestuple, typegen now emits{ id, loaderData: Info["loaderData"] }instead of{ id, module: typeof import("./self") }.Info["loaderData"]is computed viaGetLoaderData, which only accesses["loader"]and["clientLoader"], not["default"], so the cycle never forms.This required adding
MatchInfoWithLoaderData(withmodule?: neverto keep theMatchData<T>discriminant disjoint fromMatchInfo) and corresponding updates toMatch<T>,Matches<T>,MetaMatch<T>, andMetaMatches<T>to acceptAnyMatchInfo = MatchInfo | MatchInfoWithLoaderData. The loaderData type is identical to what the module path produced before; only the resolution path changes.Closes #12499