[Router/FS] Trailing slash in routePathFromFile breaks TypeScript inference for nested paths in `paths` proxy
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 2/5
- Temps estimé
- 1-3 heures
- Accessibilité débutants
- 85/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- Active
- Stack technique
- typescript
- Domaine
- web-dev
Piste de recherche
Commencez dans filesystem-routing/dist/convention.js, au niveau de routePathFromFile, et reproduisez le chemin généré à partir de la structure de route posts/[id]/index.tsx. Vérifiez la déclaration générée et l’inférence TypeScript de paths.posts(id).edit(). C’est terminé lorsque les routes index génèrent /posts/:id sans barre oblique finale et que l’appel aux paths imbriqués se compile correctement.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Describe the bug
When using file-system routing with index.tsx inside dynamic route folders, filesystem-routing produces paths with an unintended trailing slash (e.g. /posts/:id/ instead of /posts/:id).
This trailing slash causes @solidjs/router's type generator (SegmentsOf) to split the path into ["posts", ":id", ""] with a phantom empty segment "" at the end. As a result:
- When calling a nested subpath on the
pathsproxy:paths.posts(id).edit(), TypeScript selects the first matching overload signature (which terminated atPathEnddue to the empty segment) and throws:error TS2339: Property 'edit' does not exist on type 'PathEnd<DefaultSearchTypes, { id: string; }>'. - Meanwhile, at runtime,
createPathsProxyworks completely fine and outputs"/posts/1/edit".
Your Example Website or App
Blank
Steps to Reproduce the Bug or Issue
Step 1: In a project using @solidjs/router/fs and filesystem-routing, create the following route structure:
src/routes/
└── posts/
├── [id]/
│ ├── index.tsx # Post detail
│ └── edit.tsx # Post edit
└── index.tsx # Posts list
Step 2: Generate the route types using fileRoutes({ types: true }).
Notice in the generated declaration, the route path is emitted with a trailing slash:
path: "/posts/:id/"
Step 3: Attempt to use the typed paths proxy in any component:
import { paths } from "~/router";
// ❌ TypeScript Error: Property 'edit' does not exist on type 'PathEnd<...>'
paths.posts(1).edit();
Minimal TypeScript reproduction (no file system needed):
import { createRouter, defineRoutes } from "@solidjs/router";
const Router = createRouter({
routes: defineRoutes([
{ path: "/posts/:id/" }, // generated from [id]/index.tsx
{ path: "/posts/:id/edit" } // generated from [id]/edit.tsx
])
});
// ❌ TypeScript Error: Property 'edit' does not exist on type 'PathEnd<...>'
Router.paths.posts(1).edit();
// ✅ If the trailing slash is removed, it compiles cleanly:
const FixedRouter = createRouter({
routes: defineRoutes([
{ path: "/posts/:id" },
{ path: "/posts/:id/edit" }
])
});
FixedRouter.paths.posts(1).edit(); // OK!
Expected behavior
filesystem-routingshould emit/posts/:id(without trailing slash) forposts/[id]/index.tsx.paths.posts(id).edit()should be accepted by TypeScript and infer the full path"/posts/1/edit"without type errors.
Screenshots or Videos
No response
Platform
- OS: Windows 10
- Node: 24
- SolidJS:
2.0.0-rc.6 @solidjs/router:2.0.0-next.34(latest)filesystem-routing:0.4.0(latest)- TypeScript:
5.9.2
Additional context
The bug originates in filesystem-routing/dist/convention.js:
export function routePathFromFile(routeFile) {
const routePath = routeFile
.slice(1)
.replace(/(^|\/)index$/, "$1") // ⚠️ BUG: Replaces "/index" with "$1" ("/") instead of stripping the slash
.replace(/\[([^/]+)\]/g, ...);
return routePath?.length > 0 ? `/${routePath}` : "/";
}
Replacing /(^|\/)index$/ with $1 preserves the preceding slash, turning posts/[id]/index into posts/[id]/.
Proposed fix:
- .replace(/(^|\/)index$/, "$1")
+ .replace(/\/index$/, "")
Or normalize trailing slashes on all non-root routes:
return routePath?.length > 0 ? `/${routePath.replace(/\/+$/, "")}` : "/";
- Langage dominant
- TypeScript
- Étoiles
- 1.3k
- Forks
- 183
- Merge moyen
- 14 h 35 min
- PR mergées (30 j)
- 52
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Aucun modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de solidjs/solid-router
-
Difficulté 4/5 1-2 jours Accessibilité débutants 54/100
solidjs/solid-router#687 ·
Les mainteneurs répondent en général sous 1 jour
-
<A> costs ~6us of server CPU per instance during SSR (20x a plain <a>), mostly mergeProps/splitPropsPeut-être pris @birkskyum l’a pris il y a 69 jours. Ouverte1.x
Difficulté 4/5 3-5 jours Accessibilité débutants 55/100
solidjs/solid-router#583 ·
Les mainteneurs répondent en général sous 1 jour
-
1.x enhancement
Difficulté 3/5 1-2 jours Accessibilité débutants 38/100
solidjs/solid-router#518 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 4/5 3-5 jours Accessibilité débutants 35/100
solidjs/solid-router#482 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
enhancement
Difficulté 4/5 3-5 jours Accessibilité débutants 25/100
solidjs/solid-router#459 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de solidjs/solid-router
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
Les mainteneurs répondent en général sous 1 jour
-
auth: agent-bearer --manager-call is told to use the MCP instance argument on an ambiguous managerOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 80/100
Les mainteneurs répondent en général sous 1 jour
-
Lyric and ApostrophesOuvertebug module: playback
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
chthollyphile/folia-major#739 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 90/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
agilepathway/label-checker#773 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour