Repository: TanStack/router
Pull request #2312 (2024-09-10 12:12:49)

fix(router-generator): `disableTypes` option not being enforced
From https://discord.com/channels/719702312431386674/1007702008448426065/1283024763156959252

The `disableTypes` option wasn't being respected when writing the output to the generated route-tree file.

pkg-pr-new[bot]: 
[Open in Stackblitz](https://pkg.pr.new/template/118c538b-31f7-42dd-a30e-c1fb6c88e01b)
<details><summary><b>More templates</b></summary><p>

- [tanstack-router-react-example-authenticated-routes](https://pkg.pr.new/template/a99b3b70-c473-4627-83ad-65dfc752256e)
- [tanstack-router-react-example-basic](https://pkg.pr.new/template/9015d90d-6f3e-4641-ac94-d2b8f2dfbe9a)
- [tanstack-router-react-example-basic-default-search-params](https://pkg.pr.new/template/6ee200ac-475b-4f11-97bd-674933effe7c)
- [tanstack-router-react-example-basic-file-based](https://pkg.pr.new/template/d7ce386c-7780-4b9c-bf9c-a2eead02c91c)
- [tanstack-router-react-example-basic-file-based-codesplitting](https://pkg.pr.new/template/e7156357-2125-4630-9da7-a0ee2ecd5e87)
- [tanstack-router-react-example-react-query](https://pkg.pr.new/template/1e3acf3a-db3b-47d1-8749-79eacd956ff9)
- [tanstack-router-react-example-basic-react-query-file-based](https://pkg.pr.new/template/bb5386b5-7f96-4065-a2e1-6aca0ab59742)
- [tanstack-router-react-example-basic-ssr-file-based](https://pkg.pr.new/template/ddabeef9-817d-4495-a7be-ef0859b074ee)
- [tanstack-router-react-example-basic-ssr-streaming-file-based](https://pkg.pr.new/template/1338ca96-e308-4879-940d-3650c929d857)
- [tanstack-router-react-example-basic-virtual-file-based](https://pkg.pr.new/template/9afbcd47-e599-497b-975e-b0f9c3ce3d93)
- [tanstack-router-react-example-basic-virtual-inside-file-based](https://pkg.pr.new/template/915cb35d-d0c0-4a5b-8629-cbc3bdd5912d)
- [tanstack-router-react-example-deferred-data](https://pkg.pr.new/template/01514ebc-02f8-4630-971e-5191ad71a9ff)
- [tanstack-router-react-example-kitchen-sink](https://pkg.pr.new/template/41689e4b-b5fa-454d-9457-e32545da4eba)
- [tanstack-router-react-example-kitchen-sink-file-based](https://pkg.pr.new/template/359781fa-071c-4869-9ae3-745756a33296)
- [tanstack-router-react-example-kitchen-sink-react-query](https://pkg.pr.new/template/427f0d49-84a8-4edc-8454-91765478ddce)
- [tanstack-router-react-example-kitchen-sink-react-query-file-based](https://pkg.pr.new/template/fa03a9bc-8fdd-4336-a5ed-257c9f3f3412)
- [tanstack-router-react-example-large-file-based](https://pkg.pr.new/template/d66abb8f-7645-4a42-991d-ba1d40eaf8bc)
- [tanstack-router-react-example-location-masking](https://pkg.pr.new/template/cc308fc2-f217-4d53-b031-263179f18d07)
- [tanstack-router-react-example-navigation-blocking](https://pkg.pr.new/template/ac24d28f-c283-44ae-97f1-bf04e5f5e5be)
- [tanstack-router-react-example-quickstart](https://pkg.pr.new/template/5a2e7491-2fd9-4227-9b3f-0f3970e889ee)
- [tanstack-router-react-example-quickstart-file-based](https://pkg.pr.new/template/836c3fa4-ca72-4ba0-9348-b7ae4a2f1a80)
- [tanstack-router-react-example-quickstart-rspack-file-based](https://pkg.pr.new/template/99577d54-ca5f-426e-8a6b-956b6a57ced9)
- [tanstack-router-react-example-quickstart-webpack-file-based](https://pkg.pr.new/template/d0910512-f93b-418d-91aa-d79a961ae937)
- [tanstack-router-react-example-scroll-restoration](https://pkg.pr.new/template/d7145512-adbc-4d18-a359-2d5499678405)
- [tanstack-router-search-validator-adapters](https://pkg.pr.new/template/c4cfb497-cba2-48d7-8d4e-dab21253bed3)
- [tanstack-router-example-react-start-basic](https://pkg.pr.new/template/53353665-ee31-4b74-a0d0-4ddeafc76849)
- [tanstack-router-example-react-start-basic-auth](https://pkg.pr.new/template/5bb96772-ca4b-4278-be5f-480032ea6d06)
- [tanstack-router-example-react-start-basic-counter](https://pkg.pr.new/template/7812c8e9-6948-4502-aaab-ab5cbb672c6a)
- [tanstack-router-example-react-start-basic-react-query](https://pkg.pr.new/template/aa36d47f-7278-43cc-9bc5-8232d2c40322)
- [tanstack-router-example-react-start-basic-rsc](https://pkg.pr.new/template/9b627edb-b6d7-4e51-b653-800e20a4017b)
- [tanstack-router-example-react-start-clerk-basic](https://pkg.pr.new/template/80252d9d-f935-4058-b4e0-c51c3d7f99bf)
- [tanstack-router-example-react-start-trello-trellaux](https://pkg.pr.new/template/510a9008-20e6-4960-93cb-cd035ee34fad)
- [tanstack-router-example-react-start-supabase-basic](https://pkg.pr.new/template/afde3887-0d7d-476d-9f1c-ef1671c5e044)
- [tanstack-router-example-react-start-trellaux](https://pkg.pr.new/template/da5f9f5e-f376-4abd-bf8b-e36c89959925)
- [tanstack-router-react-example-with-framer-motion](https://pkg.pr.new/template/2dd4ba47-047b-4134-84c7-d20e44fb9ca7)
- [tanstack-router-react-example-with-trpc](https://pkg.pr.new/template/24db1f86-8a4c-443b-bb7f-92f6ef0fa430)
- [tanstack-router-react-example-with-trpc-react-query](https://pkg.pr.new/template/1ede65ab-1138-4813-bf31-19c4f947202a)

</p></details>
      
    


<details><summary><b>@tanstack/create-router</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/create-router@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/react-cross-context</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/react-cross-context@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/history</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/history@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/react-router-with-query</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/react-router-with-query@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/react-router</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/react-router@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/router-arktype-adapter</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-arktype-adapter@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/router-cli</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-cli@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/router-generator</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-generator@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/router-devtools</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-devtools@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/router-plugin</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-plugin@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/router-valibot-adapter</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-valibot-adapter@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/router-vite-plugin</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-vite-plugin@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/router-zod-adapter</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-zod-adapter@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/start</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/start@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/start-vite-plugin</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/start-vite-plugin@2312
```

</p></details>
      
    

<details><summary><b>@tanstack/virtual-file-routes</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/virtual-file-routes@2312
```

</p></details>
      
    

_commit: <a href="https://github.com/TanStack/router/runs/29931350210"><code>bfdf9dd</code></a>_


Patch:
diff --git a/packages/router-generator/src/generator.ts b/packages/router-generator/src/generator.ts
index fdfa18639..e3b1b4694 100644
--- a/packages/router-generator/src/generator.ts
+++ b/packages/router-generator/src/generator.ts
@@ -61,6 +61,8 @@ export async function generator(config: Config) {
 
   const start = Date.now()
 
+  const TYPES_DISABLED = config.disableTypes
+
   const prettierOptions: prettier.Options = {
     semi: config.semicolons,
     singleQuote: config.quoteStyle === 'single',
@@ -393,13 +395,15 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
       if (node.children?.length) {
         const childConfigs = buildRouteTreeConfig(node.children, depth + 1)
 
-        const childrenDeclaration = `interface ${route}Children {
-          ${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}
-        }`
+        const childrenDeclaration = TYPES_DISABLED
+          ? ''
+          : `interface ${route}Children {
+  ${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}
+}`
 
-        const children = `const ${route}Children: ${route}Children = {
-          ${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}
-        }`
+        const children = `const ${route}Children${TYPES_DISABLED ? '' : `: ${route}Children`} = {
+  ${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}
+}`
 
         const routeWithChildren = `const ${route}WithChildren = ${route}._addFileChildren(${route}Children)`
 
@@ -502,7 +506,7 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
           ]
             .filter(Boolean)
             .join(',')}
-        }${config.disableTypes ? '' : 'as any'})`,
+        }${TYPES_DISABLED ? '' : 'as any'})`,
           loaderNode
             ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(
                 removeExt(
@@ -557,7 +561,7 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
         ].join('')
       })
       .join('\n\n'),
-    ...(config.disableTypes
+    ...(TYPES_DISABLED
       ? []
       : [
           '// Populate the FileRoutesByPath interface',
@@ -589,43 +593,45 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
         ]),
     '// Create and export the route tree',
     routeConfigChildrenText,
-    `export interface FileRoutesByFullPath {
-        ${[...createRouteNodesByFullPath(routeNodes).entries()].map(
-          ([fullPath, routeNode]) => {
-            return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`
-          },
-        )}
-  }`,
-    `export interface FileRoutesByTo {
-      ${[...createRouteNodesByTo(routeNodes).entries()].map(
-        ([to, routeNode]) => {
-          return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`
-        },
-      )}
-    }`,
-    `export interface FileRoutesById {
-      '__root__': typeof rootRoute,
-      ${[...createRouteNodesById(routeNodes).entries()].map(
-        ([id, routeNode]) => {
-          return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`
-        },
-      )}
-    }`,
-    `export interface FileRouteTypes {
-    fileRoutesByFullPath: FileRoutesByFullPath
-    fullPaths: ${[...createRouteNodesByFullPath(routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join('|')}
-    fileRoutesByTo: FileRoutesByTo
-    to: ${[...createRouteNodesByTo(routeNodes).keys()].map((to) => `'${to}'`).join('|')}
-    id: '__root__' | ${[...createRouteNodesById(routeNodes).keys()].map((id) => `'${id}'`).join('|')}
-    fileRoutesById: FileRoutesById
-    }`,
-    `export interface RootRouteChildren {
+    ...(TYPES_DISABLED
+      ? []
+      : [
+          `export interface FileRoutesByFullPath {
+  ${[...createRouteNodesByFullPath(routeNodes).entries()].map(
+    ([fullPath, routeNode]) => {
+      return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`
+    },
+  )}
+}`,
+          `export interface FileRoutesByTo {
+  ${[...createRouteNodesByTo(routeNodes).entries()].map(([to, routeNode]) => {
+    return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`
+  })}
+}`,
+          `export interface FileRoutesById {
+  '__root__': typeof rootRoute,
+  ${[...createRouteNodesById(routeNodes).entries()].map(([id, routeNode]) => {
+    return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`
+  })}
+}`,
+          `export interface FileRouteTypes {
+  fileRoutesByFullPath: FileRoutesByFullPath
+  fullPaths: ${[...createRouteNodesByFullPath(routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join('|')}
+  fileRoutesByTo: FileRoutesByTo
+  to: ${[...createRouteNodesByTo(routeNodes).keys()].map((to) => `'${to}'`).join('|')}
+  id: '__root__' | ${[...createRouteNodesById(routeNodes).keys()].map((id) => `'${id}'`).join('|')}
+  fileRoutesById: FileRoutesById
+}`,
+          `export interface RootRouteChildren {
       ${routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}
-    }`,
-    `const rootRouteChildren: RootRouteChildren = {
+}`,
+          `const rootRouteChildren: RootRouteChildren = {
       ${routeTree.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}
-    }`,
-    `export const routeTree = rootRoute._addFileChildren(rootRouteChildren)._addFileTypes<FileRouteTypes>()`,
+}`,
+        ]),
+    TYPES_DISABLED
+      ? `export const routeTree = rootRoute._addFileChildren(rootRouteChildren)`
+      : `export const routeTree = rootRoute._addFileChildren(rootRouteChildren)._addFileTypes<FileRouteTypes>()`,
     ...config.routeTreeFileFooter,
   ]
     .filter(Boolean)


Test patch:
diff --git a/packages/router-generator/tests/generator.test.ts b/packages/router-generator/tests/generator.test.ts
index b16745e17..4ca9b4df0 100644
--- a/packages/router-generator/tests/generator.test.ts
+++ b/packages/router-generator/tests/generator.test.ts
@@ -76,6 +76,11 @@ function rewriteConfigByFolderName(folderName: string, config: Config) {
         config.virtualRouteConfig = virtualRouteConfig
       }
       break
+    case 'types-disabled':
+      config.disableTypes = true
+      config.generatedRouteTree =
+        makeFolderDir(folderName) + '/routeTree.gen.js'
+      break
     default:
       break
   }
@@ -144,7 +149,11 @@ describe('generator works', async () => {
       const generatedRouteTree = await getRouteTreeFileText(config)
 
       expect(generatedRouteTree).toMatchFileSnapshot(
-        join('generator', folderName, 'routeTree.snapshot.ts'),
+        join(
+          'generator',
+          folderName,
+          `routeTree.snapshot.${config.disableTypes ? 'js' : 'ts'}`,
+        ),
       )
       await postprocess(folderName)
     },
diff --git a/packages/router-generator/tests/generator/types-disabled/routeTree.gen.js b/packages/router-generator/tests/generator/types-disabled/routeTree.gen.js
new file mode 100644
index 000000000..317e32798
--- /dev/null
+++ b/packages/router-generator/tests/generator/types-disabled/routeTree.gen.js
@@ -0,0 +1,43 @@
+/* prettier-ignore-start */
+
+/* eslint-disable */
+
+// @ts-nocheck
+
+// noinspection JSUnusedGlobalSymbols
+
+// This file is auto-generated by TanStack Router
+
+// Import Routes
+
+import { Route as rootRoute } from './routes/__root'
+import { Route as IndexImport } from './routes/index'
+
+// Create/Update Routes
+
+const IndexRoute = IndexImport.update({
+  path: '/',
+  getParentRoute: () => rootRoute,
+})
+
+// Create and export the route tree
+
+export const routeTree = rootRoute._addFileChildren(rootRouteChildren)
+
+/* prettier-ignore-end */
+
+/* ROUTE_MANIFEST_START
+{
+  "routes": {
+    "__root__": {
+      "filePath": "__root.tsx",
+      "children": [
+        "/"
+      ]
+    },
+    "/": {
+      "filePath": "index.tsx"
+    }
+  }
+}
+ROUTE_MANIFEST_END */
diff --git a/packages/router-generator/tests/generator/types-disabled/routeTree.snapshot.js b/packages/router-generator/tests/generator/types-disabled/routeTree.snapshot.js
new file mode 100644
index 000000000..317e32798
--- /dev/null
+++ b/packages/router-generator/tests/generator/types-disabled/routeTree.snapshot.js
@@ -0,0 +1,43 @@
+/* prettier-ignore-start */
+
+/* eslint-disable */
+
+// @ts-nocheck
+
+// noinspection JSUnusedGlobalSymbols
+
+// This file is auto-generated by TanStack Router
+
+// Import Routes
+
+import { Route as rootRoute } from './routes/__root'
+import { Route as IndexImport } from './routes/index'
+
+// Create/Update Routes
+
+const IndexRoute = IndexImport.update({
+  path: '/',
+  getParentRoute: () => rootRoute,
+})
+
+// Create and export the route tree
+
+export const routeTree = rootRoute._addFileChildren(rootRouteChildren)
+
+/* prettier-ignore-end */
+
+/* ROUTE_MANIFEST_START
+{
+  "routes": {
+    "__root__": {
+      "filePath": "__root.tsx",
+      "children": [
+        "/"
+      ]
+    },
+    "/": {
+      "filePath": "index.tsx"
+    }
+  }
+}
+ROUTE_MANIFEST_END */
diff --git a/packages/router-generator/tests/generator/types-disabled/routes/__root.tsx b/packages/router-generator/tests/generator/types-disabled/routes/__root.tsx
new file mode 100644
index 000000000..f89644e82
--- /dev/null
+++ b/packages/router-generator/tests/generator/types-disabled/routes/__root.tsx
@@ -0,0 +1,11 @@
+import * as React from 'react'
+import { Outlet, createRootRoute } from '@tanstack/react-router'
+
+export const Route = createRootRoute({
+  component: () => (
+    <React.Fragment>
+      <div>Hello "__root"!</div>
+      <Outlet />
+    </React.Fragment>
+  ),
+})
diff --git a/packages/router-generator/tests/generator/types-disabled/routes/index.tsx b/packages/router-generator/tests/generator/types-disabled/routes/index.tsx
new file mode 100644
index 000000000..578ef7560
--- /dev/null
+++ b/packages/router-generator/tests/generator/types-disabled/routes/index.tsx
@@ -0,0 +1,6 @@
+import React from 'react'
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/')({
+  component: () => <div>Hello /!</div>,
+})