@tanstack/router-core 0.0.1-beta.152 → 0.0.1-beta.153

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/routeInfo.ts CHANGED
@@ -1,152 +1,71 @@
1
1
  import { AnyRoute, Route } from './route'
2
- import { AnyPathParams, AnySearchSchema, RootRouteId } from './route'
3
- import { IsAny, MergeUnion, Values } from './utils'
2
+ import { MergeUnion } from './utils'
4
3
 
5
- export interface AnyRoutesInfo {
6
- routeTree: AnyRoute
7
- routeUnion: AnyRoute
8
- routesById: Record<string, AnyRoute>
9
- routesByFullPath: Record<string, AnyRoute>
10
- routeIds: any
11
- routePaths: any
12
- routeIntersection: AnyRoute
13
- fullSearchSchema: Record<string, any>
14
- allParams: Record<string, any>
15
- }
16
-
17
- export interface DefaultRoutesInfo {
18
- routeTree: AnyRoute
19
- routeUnion: AnyRoute
20
- routesById: Record<string, Route>
21
- routesByFullPath: Record<string, Route>
22
- routeIds: string
23
- routePaths: string
24
- routeIntersection: AnyRoute
25
- fullSearchSchema: AnySearchSchema
26
- allParams: AnyPathParams
27
- }
4
+ export type ParseRoute<TRouteTree extends AnyRoute> =
5
+ | TRouteTree
6
+ | ParseRouteChildren<TRouteTree>
28
7
 
29
- export interface RoutesInfo<TRouteTree extends AnyRoute = Route>
30
- extends RoutesInfoInner<TRouteTree, ParseRoute<TRouteTree>> {}
31
-
32
- export interface RoutesInfoInner<
33
- TRouteTree extends AnyRoute,
34
- TRouteUnion extends AnyRoute = Route,
35
- TRoutesById = { '/': TRouteUnion } & {
36
- [TRoute in TRouteUnion as TRoute['id']]: TRoute
37
- },
38
- // RoutePaths should always use index routes if possible, but not
39
- // force trailing slashes. To do this, we check if each route
40
- // has an index route registered and if it does, we omit the layout
41
- // route. Then for any index routes, we remove the trailing slash
42
- TRoutesByFullPath = { '/': TRouteUnion } & {
43
- [TRoute in TRouteUnion as TRoute['fullPath'] extends RootRouteId
44
- ? never
45
- : string extends TRoute['fullPath']
46
- ? never
47
- : `${TRoute['fullPath']}/` extends keyof TRoutesById
48
- ? never
49
- : TRoute['fullPath'] extends `${infer Trimmed}/`
50
- ? Trimmed
51
- : TRoute['fullPath']]: TRoute
52
- },
53
- > {
54
- routeTree: TRouteTree
55
- routeUnion: TRouteUnion
56
- routesById: TRoutesById
57
- routesByFullPath: TRoutesByFullPath
58
- routeIds: keyof TRoutesById
59
- routePaths: keyof TRoutesByFullPath
60
- routeIntersection: Route<
61
- TRouteUnion['__types']['parentRoute'], // TParentRoute,
62
- TRouteUnion['__types']['path'], // TPath,
63
- TRouteUnion['__types']['fullPath'], // TFullPath,
64
- TRouteUnion['__types']['customId'], // TCustomId,
65
- TRouteUnion['__types']['id'], // TId,
66
- TRouteUnion['__types']['loader'], // TId,
67
- MergeUnion<TRouteUnion['__types']['searchSchema']> & {}, // TSearchSchema,
68
- MergeUnion<TRouteUnion['__types']['fullSearchSchema']> & {}, // TFullSearchSchema,
69
- MergeUnion<TRouteUnion['__types']['params']>, // TParams,
70
- MergeUnion<TRouteUnion['__types']['allParams']>, // TAllParams,
71
- MergeUnion<TRouteUnion['__types']['parentContext']>, // TParentContext,
72
- MergeUnion<TRouteUnion['__types']['allParentContext']>, // TAllParentContext,
73
- MergeUnion<TRouteUnion['__types']['routeContext']> & {}, // TRouteContext,
74
- MergeUnion<TRouteUnion['__types']['context']> & {}, // TContext,
75
- MergeUnion<TRouteUnion['__types']['routerContext']> & {}, // TRouterContext,
76
- TRouteUnion['__types']['children'], // TChildren,
77
- TRouteUnion['__types']['routesInfo'] // TRoutesInfo,
8
+ export type ParseRouteChildren<TRouteTree extends AnyRoute> =
9
+ TRouteTree extends Route<
10
+ any,
11
+ any,
12
+ any,
13
+ any,
14
+ any,
15
+ any,
16
+ any,
17
+ any,
18
+ any,
19
+ any,
20
+ any,
21
+ any,
22
+ any,
23
+ any,
24
+ any,
25
+ infer TChildren,
26
+ any
78
27
  >
79
- fullSearchSchema: Partial<
80
- MergeUnion<TRouteUnion['__types']['fullSearchSchema']>
81
- >
82
- allParams: Partial<MergeUnion<TRouteUnion['__types']['allParams']>>
83
- }
28
+ ? unknown extends TChildren
29
+ ? never
30
+ : TChildren extends AnyRoute[]
31
+ ? {
32
+ [TId in TChildren[number]['id'] as string]: ParseRoute<
33
+ TChildren[number]
34
+ >
35
+ }[string]
36
+ : never
37
+ : never
84
38
 
85
- export type ParseRoute<TRouteTree> = TRouteTree extends AnyRoute
86
- ? TRouteTree | ParseRouteChildren<TRouteTree>
87
- : never
39
+ export type RoutesById<TRouteTree extends AnyRoute> = {
40
+ [K in ParseRoute<TRouteTree>['id'] as K['id']]: K
41
+ }
88
42
 
89
- export type ParseRouteChildren<TRouteTree> = TRouteTree extends Route<
90
- any,
91
- any,
92
- any,
93
- any,
94
- any,
95
- any,
96
- any,
97
- any,
98
- any,
99
- any,
100
- any,
101
- any,
102
- any,
103
- any,
104
- any,
105
- infer TChildren,
106
- any
43
+ export type RouteById<TRouteTree extends AnyRoute, TId> = Extract<
44
+ ParseRoute<TRouteTree>,
45
+ { id: TId }
107
46
  >
108
- ? unknown extends TChildren
109
- ? never
110
- : TChildren extends AnyRoute[]
111
- ? Values<{
112
- [TId in TChildren[number]['id']]: ParseRouteChild<
113
- TChildren[number],
114
- TId
115
- >
116
- }>
117
- : never
118
- : never
119
47
 
120
- export type ParseRouteChild<TRoute, TId> = TRoute extends AnyRoute
121
- ? ParseRoute<TRoute>
122
- : never
48
+ export type RouteIds<TRouteTree extends AnyRoute> = AnyRoute extends TRouteTree
49
+ ? string
50
+ : ParseRoute<TRouteTree>['id']
123
51
 
124
- export type RoutesById<TRoutesInfo extends AnyRoutesInfo> = {
125
- [K in keyof TRoutesInfo['routesById']]: TRoutesInfo['routesById'][K]
52
+ export type RoutesByPath<TRouteTree extends AnyRoute> = {
53
+ [K in ParseRoute<TRouteTree>['fullPath'] as K['fullPath']]: K
126
54
  }
127
55
 
128
- export type RouteById<
129
- TRoutesInfo extends AnyRoutesInfo,
130
- TId,
131
- > = TId extends keyof TRoutesInfo['routesById']
132
- ? IsAny<
133
- TRoutesInfo['routesById'][TId]['id'],
134
- Route,
135
- TRoutesInfo['routesById'][TId]
136
- >
137
- : never
56
+ export type RouteByPath<TRouteTree extends AnyRoute, TPath> = Extract<
57
+ ParseRoute<TRouteTree>,
58
+ { fullPath: TPath }
59
+ >
138
60
 
139
- export type RoutesByPath<TRoutesInfo extends AnyRoutesInfo> = {
140
- [K in keyof TRoutesInfo['routesByFullPath']]: TRoutesInfo['routesByFullPath'][K]
141
- }
61
+ export type RoutePaths<TRouteTree extends AnyRoute> =
62
+ | ParseRoute<TRouteTree>['fullPath']
63
+ | '/'
142
64
 
143
- export type RouteByPath<
144
- TRoutesInfo extends AnyRoutesInfo,
145
- TPath,
146
- > = TPath extends keyof TRoutesInfo['routesByFullPath']
147
- ? IsAny<
148
- TRoutesInfo['routesByFullPath'][TPath]['id'],
149
- Route,
150
- TRoutesInfo['routesByFullPath'][TPath]
151
- >
152
- : never
65
+ export type FullSearchSchema<TRouteTree extends AnyRoute> = MergeUnion<
66
+ ParseRoute<TRouteTree>['__types']['fullSearchSchema']
67
+ > & {}
68
+
69
+ export type AllParams<TRouteTree extends AnyRoute> = MergeUnion<
70
+ ParseRoute<TRouteTree>['__types']['allParams']
71
+ >
package/src/router.ts CHANGED
@@ -24,7 +24,6 @@ import {
24
24
  Route,
25
25
  AnySearchSchema,
26
26
  AnyRoute,
27
- RootRoute,
28
27
  AnyContext,
29
28
  AnyPathParams,
30
29
  RouteProps,
@@ -32,11 +31,12 @@ import {
32
31
  RegisteredRouteErrorComponent,
33
32
  } from './route'
34
33
  import {
35
- RoutesInfo,
36
- AnyRoutesInfo,
37
34
  RoutesById,
38
35
  RoutesByPath,
39
- DefaultRoutesInfo,
36
+ ParseRoute,
37
+ FullSearchSchema,
38
+ RouteById,
39
+ RoutePaths,
40
40
  } from './routeInfo'
41
41
  import { defaultParseSearch, defaultStringifySearch } from './searchParams'
42
42
  import {
@@ -68,28 +68,25 @@ export interface Register {
68
68
  // router: Router
69
69
  }
70
70
 
71
- export type AnyRouter = Router<any, any, any>
71
+ export type AnyRouter = Router<any, any>
72
72
 
73
- export type RegisteredRouterPair = Register extends {
73
+ export type RegisteredRouter = Register extends {
74
74
  router: infer TRouter extends AnyRouter
75
75
  }
76
- ? [TRouter, TRouter['types']['RoutesInfo']]
77
- : [Router, AnyRoutesInfo]
78
-
79
- export type RegisteredRouter = RegisteredRouterPair[0]
80
- export type RegisteredRoutesInfo = RegisteredRouterPair[1]
76
+ ? TRouter
77
+ : Router
81
78
 
82
79
  export interface LocationState {}
83
80
 
84
81
  export interface ParsedLocation<
85
82
  TSearchObj extends AnySearchSchema = {},
86
- TState extends LocationState = LocationState,
83
+ // TState extends LocationState = LocationState,
87
84
  > {
88
85
  href: string
89
86
  pathname: string
90
87
  search: TSearchObj
91
88
  searchStr: string
92
- state: TState
89
+ state: LocationState
93
90
  hash: string
94
91
  key?: string
95
92
  }
@@ -110,7 +107,7 @@ export type HydrationCtx = {
110
107
  }
111
108
 
112
109
  export interface RouteMatch<
113
- TRoutesInfo extends AnyRoutesInfo = DefaultRoutesInfo,
110
+ TRouteTree extends AnyRoute = AnyRoute,
114
111
  TRoute extends AnyRoute = Route,
115
112
  > {
116
113
  id: string
@@ -133,13 +130,12 @@ export interface RouteMatch<
133
130
  routeContext: TRoute['__types']['routeContext']
134
131
  context: TRoute['__types']['context']
135
132
  routeSearch: TRoute['__types']['searchSchema']
136
- search: TRoutesInfo['fullSearchSchema'] &
137
- TRoute['__types']['fullSearchSchema']
133
+ search: FullSearchSchema<TRouteTree> & TRoute['__types']['fullSearchSchema']
138
134
  fetchedAt: number
139
135
  abortController: AbortController
140
136
  }
141
137
 
142
- export type AnyRouteMatch = RouteMatch<AnyRoutesInfo, AnyRoute>
138
+ export type AnyRouteMatch = RouteMatch<AnyRoute, AnyRoute>
143
139
 
144
140
  export type RouterContextOptions<TRouteTree extends AnyRoute> =
145
141
  AnyContext extends TRouteTree['__types']['routerContext']
@@ -186,21 +182,18 @@ export interface RouterOptions<
186
182
  }
187
183
 
188
184
  export interface RouterState<
189
- TRoutesInfo extends AnyRoutesInfo = AnyRoutesInfo,
190
- TState extends LocationState = LocationState,
185
+ TRouteTree extends AnyRoute = AnyRoute,
186
+ // TState extends LocationState = LocationState,
191
187
  > {
192
188
  status: 'idle' | 'pending'
193
189
  isFetching: boolean
194
- matchesById: Record<
195
- string,
196
- RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>
197
- >
190
+ matchesById: Record<string, RouteMatch<any, any>>
198
191
  matchIds: string[]
199
192
  pendingMatchIds: string[]
200
- matches: RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>[]
201
- pendingMatches: RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>[]
202
- location: ParsedLocation<TRoutesInfo['fullSearchSchema'], TState>
203
- resolvedLocation: ParsedLocation<TRoutesInfo['fullSearchSchema'], TState>
193
+ matches: RouteMatch<any, any>[]
194
+ pendingMatches: RouteMatch<any, any>[]
195
+ location: ParsedLocation<FullSearchSchema<TRouteTree>>
196
+ resolvedLocation: ParsedLocation<FullSearchSchema<TRouteTree>>
204
197
  lastUpdated: number
205
198
  }
206
199
 
@@ -258,12 +251,10 @@ export const componentTypes = [
258
251
 
259
252
  export class Router<
260
253
  TRouteTree extends AnyRoute = AnyRoute,
261
- TRoutesInfo extends AnyRoutesInfo = RoutesInfo<TRouteTree>,
262
254
  TDehydrated extends Record<string, any> = Record<string, any>,
263
255
  > {
264
256
  types!: {
265
257
  RootRoute: TRouteTree
266
- RoutesInfo: TRoutesInfo
267
258
  }
268
259
 
269
260
  options: PickAsRequired<
@@ -273,16 +264,16 @@ export class Router<
273
264
  history!: RouterHistory
274
265
  #unsubHistory?: () => void
275
266
  basepath!: string
276
- routeTree!: RootRoute
277
- routesById!: RoutesById<TRoutesInfo>
278
- routesByPath!: RoutesByPath<TRoutesInfo>
279
- flatRoutes!: TRoutesInfo['routesByFullPath'][keyof TRoutesInfo['routesByFullPath']][]
267
+ routeTree!: TRouteTree
268
+ routesById!: RoutesById<TRouteTree>
269
+ routesByPath!: RoutesByPath<TRouteTree>
270
+ flatRoutes!: ParseRoute<TRouteTree>[]
280
271
  navigateTimeout: undefined | Timeout
281
272
  nextAction: undefined | 'push' | 'replace'
282
273
  navigationPromise: undefined | Promise<void>
283
274
 
284
- __store: Store<RouterState<TRoutesInfo>>
285
- state: RouterState<TRoutesInfo>
275
+ __store: Store<RouterState<TRouteTree>>
276
+ state: RouterState<TRouteTree>
286
277
  dehydratedData?: TDehydrated
287
278
 
288
279
  constructor(options: RouterConstructorOptions<TRouteTree, TDehydrated>) {
@@ -295,51 +286,47 @@ export class Router<
295
286
  // fetchServerDataFn: options?.fetchServerDataFn ?? defaultFetchServerDataFn,
296
287
  }
297
288
 
298
- this.__store = new Store<RouterState<TRoutesInfo>>(
299
- getInitialRouterState(),
300
- {
301
- onUpdate: () => {
302
- const prev = this.state
303
-
304
- this.state = this.__store.state
305
-
306
- const matchesByIdChanged = prev.matchesById !== this.state.matchesById
307
- let matchesChanged
308
- let pendingMatchesChanged
309
-
310
- if (!matchesByIdChanged) {
311
- matchesChanged =
312
- prev.matchIds.length !== this.state.matchIds.length ||
313
- prev.matchIds.some((d, i) => d !== this.state.matchIds[i])
314
-
315
- pendingMatchesChanged =
316
- prev.pendingMatchIds.length !==
317
- this.state.pendingMatchIds.length ||
318
- prev.pendingMatchIds.some(
319
- (d, i) => d !== this.state.pendingMatchIds[i],
320
- )
321
- }
289
+ this.__store = new Store<RouterState<TRouteTree>>(getInitialRouterState(), {
290
+ onUpdate: () => {
291
+ const prev = this.state
322
292
 
323
- if (matchesByIdChanged || matchesChanged) {
324
- this.state.matches = this.state.matchIds.map((id) => {
325
- return this.state.matchesById[id] as any
326
- })
327
- }
293
+ this.state = this.__store.state
328
294
 
329
- if (matchesByIdChanged || pendingMatchesChanged) {
330
- this.state.pendingMatches = this.state.pendingMatchIds.map((id) => {
331
- return this.state.matchesById[id] as any
332
- })
333
- }
295
+ const matchesByIdChanged = prev.matchesById !== this.state.matchesById
296
+ let matchesChanged
297
+ let pendingMatchesChanged
334
298
 
335
- this.state.isFetching = [
336
- ...this.state.matches,
337
- ...this.state.pendingMatches,
338
- ].some((d) => d.isFetching)
339
- },
340
- defaultPriority: 'low',
299
+ if (!matchesByIdChanged) {
300
+ matchesChanged =
301
+ prev.matchIds.length !== this.state.matchIds.length ||
302
+ prev.matchIds.some((d, i) => d !== this.state.matchIds[i])
303
+
304
+ pendingMatchesChanged =
305
+ prev.pendingMatchIds.length !== this.state.pendingMatchIds.length ||
306
+ prev.pendingMatchIds.some(
307
+ (d, i) => d !== this.state.pendingMatchIds[i],
308
+ )
309
+ }
310
+
311
+ if (matchesByIdChanged || matchesChanged) {
312
+ this.state.matches = this.state.matchIds.map((id) => {
313
+ return this.state.matchesById[id] as any
314
+ })
315
+ }
316
+
317
+ if (matchesByIdChanged || pendingMatchesChanged) {
318
+ this.state.pendingMatches = this.state.pendingMatchIds.map((id) => {
319
+ return this.state.matchesById[id] as any
320
+ })
321
+ }
322
+
323
+ this.state.isFetching = [
324
+ ...this.state.matches,
325
+ ...this.state.pendingMatches,
326
+ ].some((d) => d.isFetching)
341
327
  },
342
- )
328
+ defaultPriority: 'low',
329
+ })
343
330
 
344
331
  this.state = this.__store.state
345
332
 
@@ -394,8 +381,8 @@ export class Router<
394
381
 
395
382
  this.__store.setState((s) => ({
396
383
  ...s,
397
- resolvedLocation: parsedLocation,
398
- location: parsedLocation,
384
+ resolvedLocation: parsedLocation as any,
385
+ location: parsedLocation as any,
399
386
  }))
400
387
 
401
388
  this.#unsubHistory = this.history.listen(() => {
@@ -466,7 +453,7 @@ export class Router<
466
453
  // Ingest the new location
467
454
  this.__store.setState((s) => ({
468
455
  ...s,
469
- location: opts.next!,
456
+ location: opts.next! as any,
470
457
  }))
471
458
  }
472
459
 
@@ -530,13 +517,10 @@ export class Router<
530
517
  #mergeMatches = (
531
518
  prevMatchesById: Record<
532
519
  string,
533
- RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>
520
+ RouteMatch<TRouteTree, ParseRoute<TRouteTree>>
534
521
  >,
535
522
  nextMatches: RouteMatch[],
536
- ): Record<
537
- string,
538
- RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>
539
- > => {
523
+ ): Record<string, RouteMatch<TRouteTree, ParseRoute<TRouteTree>>> => {
540
524
  const nextMatchesById: any = {
541
525
  ...prevMatchesById,
542
526
  }
@@ -557,14 +541,12 @@ export class Router<
557
541
  return nextMatchesById
558
542
  }
559
543
 
560
- getRoute = <TId extends keyof TRoutesInfo['routesById']>(
561
- id: TId,
562
- ): TRoutesInfo['routesById'][TId] => {
563
- const route = this.routesById[id]
544
+ getRoute = (id: string): Route => {
545
+ const route = (this.routesById as any)[id]
564
546
 
565
547
  invariant(route, `Route with id "${id as string}" not found`)
566
548
 
567
- return route
549
+ return route as any
568
550
  }
569
551
 
570
552
  preloadRoute = async (
@@ -627,7 +609,7 @@ export class Router<
627
609
  pathname: string,
628
610
  locationSearch: AnySearchSchema,
629
611
  opts?: { throwOnError?: boolean; debug?: boolean },
630
- ): RouteMatch<TRoutesInfo, TRoutesInfo['routeIntersection']>[] => {
612
+ ): RouteMatch<TRouteTree, ParseRoute<TRouteTree>>[] => {
631
613
  let routeParams: AnyPathParams = {}
632
614
 
633
615
  let foundRoute = this.flatRoutes.find((route) => {
@@ -650,7 +632,7 @@ export class Router<
650
632
  })
651
633
 
652
634
  let routeCursor: AnyRoute =
653
- foundRoute || (this.routesById['__root__'] as any)
635
+ foundRoute || (this.routesById as any)['__root__']
654
636
 
655
637
  let matchedRoutes: AnyRoute[] = [routeCursor]
656
638
  // let includingLayouts = true
@@ -1048,14 +1030,17 @@ export class Router<
1048
1030
  return resolvePath(this.basepath!, from, cleanPath(path))
1049
1031
  }
1050
1032
 
1051
- navigate = async <TFrom extends string = '/', TTo extends string = ''>({
1033
+ navigate = async <
1034
+ TFrom extends RoutePaths<TRouteTree> = '/',
1035
+ TTo extends string = '',
1036
+ >({
1052
1037
  from,
1053
1038
  to = '' as any,
1054
1039
  search,
1055
1040
  hash,
1056
1041
  replace,
1057
1042
  params,
1058
- }: NavigateOptions<TRoutesInfo, TFrom, TTo>) => {
1043
+ }: NavigateOptions<TRouteTree, TFrom, TTo>) => {
1059
1044
  // If this link simply reloads the current route,
1060
1045
  // make sure it has a new key so it will trigger a data refresh
1061
1046
 
@@ -1086,13 +1071,13 @@ export class Router<
1086
1071
  }
1087
1072
 
1088
1073
  matchRoute = <
1089
- TFrom extends string = '/',
1074
+ TFrom extends RoutePaths<TRouteTree> = '/',
1090
1075
  TTo extends string = '',
1091
1076
  TResolved extends string = ResolveRelativePath<TFrom, NoInfer<TTo>>,
1092
1077
  >(
1093
- location: ToOptions<TRoutesInfo, TFrom, TTo>,
1078
+ location: ToOptions<TRouteTree, TFrom, TTo>,
1094
1079
  opts?: MatchRouteOptions,
1095
- ): false | TRoutesInfo['routesById'][TResolved]['__types']['allParams'] => {
1080
+ ): false | RouteById<TRouteTree, TResolved>['__types']['allParams'] => {
1096
1081
  location = {
1097
1082
  ...location,
1098
1083
  to: location.to
@@ -1129,7 +1114,10 @@ export class Router<
1129
1114
  return match
1130
1115
  }
1131
1116
 
1132
- buildLink = <TFrom extends string = '/', TTo extends string = ''>({
1117
+ buildLink = <
1118
+ TFrom extends RoutePaths<TRouteTree> = '/',
1119
+ TTo extends string = '',
1120
+ >({
1133
1121
  from,
1134
1122
  to = '.' as any,
1135
1123
  search,
@@ -1141,7 +1129,7 @@ export class Router<
1141
1129
  preload,
1142
1130
  preloadDelay: userPreloadDelay,
1143
1131
  disabled,
1144
- }: LinkOptions<TRoutesInfo, TFrom, TTo>): LinkInfo => {
1132
+ }: LinkOptions<TRouteTree, TFrom, TTo>): LinkInfo => {
1145
1133
  // If this link simply reloads the current route,
1146
1134
  // make sure it has a new key so it will trigger a data refresh
1147
1135
 
@@ -1286,12 +1274,13 @@ export class Router<
1286
1274
  const ctx = _ctx
1287
1275
  this.dehydratedData = ctx.payload as any
1288
1276
  this.options.hydrate?.(ctx.payload as any)
1277
+ const routerState = ctx.router.state as RouterState<TRouteTree>
1289
1278
 
1290
1279
  this.__store.setState((s) => {
1291
1280
  return {
1292
1281
  ...s,
1293
- ...ctx.router.state,
1294
- resolvedLocation: ctx.router.state.location,
1282
+ ...routerState,
1283
+ resolvedLocation: routerState.location,
1295
1284
  }
1296
1285
  })
1297
1286
 
@@ -1367,7 +1356,7 @@ export class Router<
1367
1356
  if (!route.isRoot && route.path) {
1368
1357
  const trimmedFullPath = trimPathRight(route.fullPath)
1369
1358
  if (
1370
- !this.routesByPath[trimmedFullPath] ||
1359
+ !(this.routesByPath as any)[trimmedFullPath] ||
1371
1360
  route.fullPath.endsWith('/')
1372
1361
  ) {
1373
1362
  ;(this.routesByPath as any)[trimmedFullPath] = route
@@ -1447,7 +1436,9 @@ export class Router<
1447
1436
  }) as any
1448
1437
  }
1449
1438
 
1450
- #parseLocation = (previousLocation?: ParsedLocation): ParsedLocation => {
1439
+ #parseLocation = (
1440
+ previousLocation?: ParsedLocation,
1441
+ ): ParsedLocation<FullSearchSchema<TRouteTree>> => {
1451
1442
  let { pathname, search, hash, state } = this.history.location
1452
1443
 
1453
1444
  const parsedSearch = this.options.parseSearch(search)
@@ -1455,7 +1446,7 @@ export class Router<
1455
1446
  return {
1456
1447
  pathname: pathname,
1457
1448
  searchStr: search,
1458
- search: replaceEqualDeep(previousLocation?.search, parsedSearch),
1449
+ search: replaceEqualDeep(previousLocation?.search, parsedSearch) as any,
1459
1450
  hash: hash.split('#').reverse()[0] ?? '',
1460
1451
  href: `${pathname}${search}${hash}`,
1461
1452
  state: state as LocationState,
@@ -1604,15 +1595,15 @@ export class Router<
1604
1595
 
1605
1596
  getRouteMatch = (
1606
1597
  id: string,
1607
- ): undefined | RouteMatch<TRoutesInfo, AnyRoute> => {
1598
+ ): undefined | RouteMatch<TRouteTree, AnyRoute> => {
1608
1599
  return this.state.matchesById[id]
1609
1600
  }
1610
1601
 
1611
1602
  setRouteMatch = (
1612
1603
  id: string,
1613
1604
  updater: (
1614
- prev: RouteMatch<TRoutesInfo, AnyRoute>,
1615
- ) => RouteMatch<TRoutesInfo, AnyRoute>,
1605
+ prev: RouteMatch<TRouteTree, AnyRoute>,
1606
+ ) => RouteMatch<TRouteTree, AnyRoute>,
1616
1607
  ) => {
1617
1608
  this.__store.setState((prev) => ({
1618
1609
  ...prev,
@@ -1725,7 +1716,7 @@ export class Router<
1725
1716
  // Detect if we're in the DOM
1726
1717
  const isServer = typeof window === 'undefined' || !window.document.createElement
1727
1718
 
1728
- function getInitialRouterState(): RouterState<any, any> {
1719
+ function getInitialRouterState(): RouterState<any> {
1729
1720
  return {
1730
1721
  status: 'idle',
1731
1722
  isFetching: false,
@@ -1747,18 +1738,18 @@ function isCtrlEvent(e: MouseEvent) {
1747
1738
  export type AnyRedirect = Redirect<any, any, any>
1748
1739
 
1749
1740
  export type Redirect<
1750
- TRoutesInfo extends AnyRoutesInfo = RegisteredRoutesInfo,
1751
- TFrom extends TRoutesInfo['routePaths'] = '/',
1741
+ TRouteTree extends AnyRoute = AnyRoute,
1742
+ TFrom extends RoutePaths<TRouteTree> = '/',
1752
1743
  TTo extends string = '',
1753
- > = NavigateOptions<TRoutesInfo, TFrom, TTo> & {
1744
+ > = NavigateOptions<TRouteTree, TFrom, TTo> & {
1754
1745
  code?: number
1755
1746
  }
1756
1747
 
1757
1748
  export function redirect<
1758
- TRoutesInfo extends AnyRoutesInfo = RegisteredRoutesInfo,
1759
- TFrom extends TRoutesInfo['routePaths'] = '/',
1749
+ TRouteTree extends AnyRoute = AnyRoute,
1750
+ TFrom extends RoutePaths<TRouteTree> = '/',
1760
1751
  TTo extends string = '',
1761
- >(opts: Redirect<TRoutesInfo, TFrom, TTo>): Redirect<TRoutesInfo, TFrom, TTo> {
1752
+ >(opts: Redirect<TRouteTree, TFrom, TTo>): Redirect<TRouteTree, TFrom, TTo> {
1762
1753
  ;(opts as any).isRedirect = true
1763
1754
  return opts
1764
1755
  }