@@ -55,8 +55,7 @@ test.describe("typegen", () => {
55
55
import type { Route } from "./+types/product"
56
56
57
57
export function loader({ params }: Route.LoaderArgs) {
58
- type Test1 = Expect<Equal<typeof params.id, string>>
59
- type Test2 = Expect<Equal<typeof params.asdf, string | undefined>>
58
+ type Test = Expect<Equal<typeof params, { id: string} >>
60
59
return { planet: "world" }
61
60
}
62
61
@@ -92,23 +91,23 @@ test.describe("typegen", () => {
92
91
import type { Expect, Equal } from "../expect-type"
93
92
import type { Route } from "./+types/only-required"
94
93
export function loader({ params }: Route.LoaderArgs) {
95
- type Test = Expect<Equal<typeof params.id, string>>
94
+ type Test = Expect<Equal<typeof params, { id: string } >>
96
95
return null
97
96
}
98
97
` ,
99
98
"app/routes/only-optional.tsx" : tsx `
100
99
import type { Expect, Equal } from "../expect-type"
101
100
import type { Route } from "./+types/only-optional"
102
101
export function loader({ params }: Route.LoaderArgs) {
103
- type Test = Expect<Equal<typeof params.id, string | undefined >>
102
+ type Test = Expect<Equal<typeof params, { id?: string } >>
104
103
return null
105
104
}
106
105
` ,
107
106
"app/routes/optional-then-required.tsx" : tsx `
108
107
import type { Expect, Equal } from "../expect-type"
109
108
import type { Route } from "./+types/optional-then-required"
110
109
export function loader({ params }: Route.LoaderArgs) {
111
- type Test = Expect<Equal<typeof params.id, string>>
110
+ type Test = Expect<Equal<typeof params, { id: string } >>
112
111
return null
113
112
}
114
113
` ,
@@ -117,7 +116,7 @@ test.describe("typegen", () => {
117
116
import type { Route } from "./+types/required-then-optional"
118
117
119
118
export function loader({ params }: Route.LoaderArgs) {
120
- type Test = Expect<Equal<typeof params.id, string>>
119
+ type Test = Expect<Equal<typeof params, { id: string } >>
121
120
return null
122
121
}
123
122
` ,
@@ -144,7 +143,7 @@ test.describe("typegen", () => {
144
143
import type { Route } from "./+types/splat"
145
144
146
145
export function loader({ params }: Route.LoaderArgs) {
147
- type Test = Expect<Equal<typeof params[ "*"], string>>
146
+ type Test = Expect<Equal<typeof params, { "*": string } >>
148
147
return null
149
148
}
150
149
` ,
@@ -172,7 +171,7 @@ test.describe("typegen", () => {
172
171
import type { Route } from "./+types/param-with-ext"
173
172
174
173
export function loader({ params }: Route.LoaderArgs) {
175
- type Test = Expect<Equal<typeof params["lang"], string>>
174
+ type Test = Expect<Equal<typeof params, { lang: string } >>
176
175
return null
177
176
}
178
177
` ,
@@ -181,7 +180,7 @@ test.describe("typegen", () => {
181
180
import type { Route } from "./+types/optional-param-with-ext"
182
181
183
182
export function loader({ params }: Route.LoaderArgs) {
184
- type Test = Expect<Equal<typeof params["user"], string | undefined >>
183
+ type Test = Expect<Equal<typeof params, { user?: string } >>
185
184
return null
186
185
}
187
186
` ,
@@ -191,6 +190,106 @@ test.describe("typegen", () => {
191
190
expect ( proc . stderr . toString ( ) ) . toBe ( "" ) ;
192
191
expect ( proc . status ) . toBe ( 0 ) ;
193
192
} ) ;
193
+
194
+ test ( "normalized params" , async ( ) => {
195
+ const cwd = await createProject ( {
196
+ "vite.config.ts" : viteConfig ,
197
+ "app/expect-type.ts" : expectType ,
198
+ "app/routes.ts" : tsx `
199
+ import { type RouteConfig, route, layout } from "@react-router/dev/routes";
200
+
201
+ export default [
202
+ route("parent/:p", "routes/parent.tsx", [
203
+ route("route/:r", "routes/route.tsx", [
204
+ route("child1/:c1a/:c1b", "routes/child1.tsx"),
205
+ route("child2/:c2a/:c2b", "routes/child2.tsx")
206
+ ]),
207
+ ]),
208
+ layout("routes/layout.tsx", [
209
+ route("in-layout1/:id", "routes/in-layout1.tsx"),
210
+ route("in-layout2/:id/:other", "routes/in-layout2.tsx")
211
+ ])
212
+ ] satisfies RouteConfig;
213
+ ` ,
214
+ "app/routes/parent.tsx" : tsx `
215
+ import type { Expect, Equal } from "../expect-type"
216
+ import type { Route } from "./+types/parent"
217
+
218
+ export function loader({ params }: Route.LoaderArgs) {
219
+ type Test = Expect<Equal<typeof params,
220
+ | { p: string, r?: undefined, c1a?: undefined, c1b?: undefined, c2a?: undefined, c2b?: undefined }
221
+ | { p: string, r: string, c1a?: undefined, c1b?: undefined, c2a?: undefined, c2b?: undefined }
222
+ | { p: string, r: string, c1a: string, c1b: string, c2a?: undefined, c2b?: undefined }
223
+ | { p: string, r: string, c1a?: undefined, c1b?: undefined, c2a: string, c2b: string }
224
+ >>
225
+ return null
226
+ }
227
+ ` ,
228
+ "app/routes/route.tsx" : tsx `
229
+ import type { Expect, Equal } from "../expect-type"
230
+ import type { Route } from "./+types/route"
231
+
232
+ export function loader({ params }: Route.LoaderArgs) {
233
+ type Test = Expect<Equal<typeof params,
234
+ | { p: string, r: string, c1a?: undefined, c1b?: undefined, c2a?: undefined, c2b?: undefined }
235
+ | { p: string, r: string, c1a: string, c1b: string, c2a?: undefined, c2b?: undefined }
236
+ | { p: string, r: string, c1a?: undefined, c1b?: undefined, c2a: string, c2b: string }
237
+ >>
238
+ return null
239
+ }
240
+ ` ,
241
+ "app/routes/child1.tsx" : tsx `
242
+ import type { Expect, Equal } from "../expect-type"
243
+ import type { Route } from "./+types/child1"
244
+
245
+ export function loader({ params }: Route.LoaderArgs) {
246
+ type Test = Expect<Equal<typeof params, { p: string, r: string, c1a: string, c1b: string }>>
247
+ return null
248
+ }
249
+ ` ,
250
+ "app/routes/child2.tsx" : tsx `
251
+ import type { Expect, Equal } from "../expect-type"
252
+ import type { Route } from "./+types/child2"
253
+
254
+ export function loader({ params }: Route.LoaderArgs) {
255
+ type Test = Expect<Equal<typeof params, { p: string, r: string, c2a: string, c2b: string }>>
256
+ return null
257
+ }
258
+ ` ,
259
+ "app/routes/layout.tsx" : tsx `
260
+ import type { Expect, Equal } from "../expect-type"
261
+ import type { Route } from "./+types/layout"
262
+
263
+ export function loader({ params }: Route.LoaderArgs) {
264
+ type Test = Expect<Equal<typeof params, { id: string, other?: undefined } | { id: string, other: string } >>
265
+ return null
266
+ }
267
+ ` ,
268
+ "app/routes/in-layout1.tsx" : tsx `
269
+ import type { Expect, Equal } from "../expect-type"
270
+ import type { Route } from "./+types/in-layout1"
271
+
272
+ export function loader({ params }: Route.LoaderArgs) {
273
+ type Test = Expect<Equal<typeof params, { id: string }>>
274
+ return null
275
+ }
276
+ ` ,
277
+ "app/routes/in-layout2.tsx" : tsx `
278
+ import type { Expect, Equal } from "../expect-type"
279
+ import type { Route } from "./+types/in-layout2"
280
+
281
+ export function loader({ params }: Route.LoaderArgs) {
282
+ type Test = Expect<Equal<typeof params, { id: string, other: string }>>
283
+ return null
284
+ }
285
+ ` ,
286
+ } ) ;
287
+
288
+ const proc = typecheck ( cwd ) ;
289
+ expect ( proc . stdout . toString ( ) ) . toBe ( "" ) ;
290
+ expect ( proc . stderr . toString ( ) ) . toBe ( "" ) ;
291
+ expect ( proc . status ) . toBe ( 0 ) ;
292
+ } ) ;
194
293
} ) ;
195
294
196
295
test ( "clientLoader.hydrate = true" , async ( ) => {
@@ -240,7 +339,7 @@ test.describe("typegen", () => {
240
339
import type { Route } from "./+types/products.$id"
241
340
242
341
export function loader({ params }: Route.LoaderArgs) {
243
- type Test = Expect<Equal<typeof params.id, string>>
342
+ type Test = Expect<Equal<typeof params, { id: string } >>
244
343
return { planet: "world" }
245
344
}
246
345
@@ -372,7 +471,7 @@ test.describe("typegen", () => {
372
471
import type { Route } from "./+types/absolute"
373
472
374
473
export function loader({ params }: Route.LoaderArgs) {
375
- type Test = Expect<Equal<typeof params.id, string>>
474
+ type Test = Expect<Equal<typeof params, { id: string } >>
376
475
return { planet: "world" }
377
476
}
378
477
0 commit comments