@@ -30,14 +30,25 @@ const viteConfig = tsx`
3030 };
3131` ;
3232
33+ const assertType = tsx `
34+ export function assertType<T>(t: T) {}
35+ ` ;
36+
3337test . describe ( "typegen" , ( ) => {
3438 test ( "basic" , async ( ) => {
3539 const cwd = await createProject ( {
3640 "vite.config.ts" : viteConfig ,
37- "app/routes/products.$id.tsx" : tsx `
38- import type { Route } from "./+types.products.$id"
41+ "app/assertType.ts" : assertType ,
42+ "app/routes.ts" : tsx `
43+ import { type RouteConfig, route } from "@react-router/dev/routes";
3944
40- function assertType<T>(t: T) {}
45+ export const routes: RouteConfig = [
46+ route("products/:id", "routes/product.tsx")
47+ ]
48+ ` ,
49+ "app/routes/product.tsx" : tsx `
50+ import { assertType } from "../assertType"
51+ import type { Route } from "./+types.product"
4152
4253 export function loader({ params }: Route.LoaderArgs) {
4354 assertType<string>(params.id)
@@ -61,10 +72,17 @@ test.describe("typegen", () => {
6172 test ( "repeated" , async ( ) => {
6273 const cwd = await createProject ( {
6374 "vite.config.ts" : viteConfig ,
64- "app/routes/repeated.$id.($id).$id.tsx" : tsx `
65- import type { Route } from "./+types.repeated.$id.($id).$id"
75+ "app/assertType.ts" : assertType ,
76+ "app/routes.ts" : tsx `
77+ import { type RouteConfig, route } from "@react-router/dev/routes";
6678
67- function assertType<T>(t: T) {}
79+ export const routes: RouteConfig = [
80+ route("repeated-params/:id/:id?/:id", "routes/repeated-params.tsx")
81+ ]
82+ ` ,
83+ "app/routes/repeated-params.tsx" : tsx `
84+ import { assertType } from "../assertType"
85+ import type { Route } from "./+types.repeated-params"
6886
6987 export function loader({ params }: Route.LoaderArgs) {
7088 assertType<[string, string | undefined, string]>(params.id)
@@ -81,10 +99,17 @@ test.describe("typegen", () => {
8199 test ( "splat" , async ( ) => {
82100 const cwd = await createProject ( {
83101 "vite.config.ts" : viteConfig ,
84- "app/routes/splat.$.tsx" : tsx `
85- import type { Route } from "./+types.splat.$"
102+ "app/assertType.ts" : assertType ,
103+ "app/routes.ts" : tsx `
104+ import { type RouteConfig, route } from "@react-router/dev/routes";
86105
87- function assertType<T>(t: T) {}
106+ export const routes: RouteConfig = [
107+ route("splat/*", "routes/splat.tsx")
108+ ]
109+ ` ,
110+ "app/routes/splat.tsx" : tsx `
111+ import { assertType } from "../assertType"
112+ import type { Route } from "./+types.splat"
88113
89114 export function loader({ params }: Route.LoaderArgs) {
90115 assertType<string>(params["*"])
@@ -97,16 +122,53 @@ test.describe("typegen", () => {
97122 expect ( proc . stderr . toString ( ) ) . toBe ( "" ) ;
98123 expect ( proc . status ) . toBe ( 0 ) ;
99124 } ) ;
125+
126+ test ( "with extension" , async ( ) => {
127+ const cwd = await createProject ( {
128+ "vite.config.ts" : viteConfig ,
129+ "app/assertType.ts" : assertType ,
130+ "app/routes.ts" : tsx `
131+ import { type RouteConfig, route } from "@react-router/dev/routes";
132+
133+ export const routes: RouteConfig = [
134+ route(":lang.xml", "routes/param-with-ext.tsx"),
135+ route(":user?.pdf", "routes/optional-param-with-ext.tsx"),
136+ ]
137+ ` ,
138+ "app/routes/param-with-ext.tsx" : tsx `
139+ import { assertType } from "../assertType"
140+ import type { Route } from "./+types.param-with-ext"
141+
142+ export function loader({ params }: Route.LoaderArgs) {
143+ assertType<string>(params["lang"])
144+ return null
145+ }
146+ ` ,
147+ "app/routes/optional-param-with-ext.tsx" : tsx `
148+ import { assertType } from "../assertType"
149+ import type { Route } from "./+types.optional-param-with-ext"
150+
151+ export function loader({ params }: Route.LoaderArgs) {
152+ assertType<string | undefined>(params["user"])
153+ return null
154+ }
155+ ` ,
156+ } ) ;
157+ const proc = typecheck ( cwd ) ;
158+ expect ( proc . stdout . toString ( ) ) . toBe ( "" ) ;
159+ expect ( proc . stderr . toString ( ) ) . toBe ( "" ) ;
160+ expect ( proc . status ) . toBe ( 0 ) ;
161+ } ) ;
100162 } ) ;
101163
102164 test ( "clientLoader.hydrate = true" , async ( ) => {
103165 const cwd = await createProject ( {
104166 "vite.config.ts" : viteConfig ,
167+ "app/assertType.ts" : assertType ,
105168 "app/routes/_index.tsx" : tsx `
169+ import { assertType } from "../assertType"
106170 import type { Route } from "./+types._index"
107171
108- function assertType<T>(t: T) {}
109-
110172 export function loader() {
111173 return { server: "server" }
112174 }
@@ -141,11 +203,11 @@ test.describe("typegen", () => {
141203 plugins: [reactRouter({ appDirectory: "src/myapp" })],
142204 };
143205 ` ,
206+ "app/assertType.ts" : assertType ,
144207 "app/routes/products.$id.tsx" : tsx `
208+ import { assertType } from "../assertType"
145209 import type { Route } from "./+types.products.$id"
146210
147- function assertType<T>(t: T) {}
148-
149211 export function loader({ params }: Route.LoaderArgs) {
150212 assertType<string>(params.id)
151213 return { planet: "world" }
0 commit comments