Currently, I am working on developing a recursive type in TypeScript to iterate through every potential route path, even nested paths, from a provided route configuration. However, I have hit a roadblock with type constraints and inference.
The routes are defined using a TypedRoute interface and a createRoute function:
interface TypedRoute<
Path extends string,
QueryParams extends Record<string, string> = {}
> {
path: Path;
queryParams?: QueryParams;
children?: TypedRoute<any, any>[];
}
function createRoute<
Path extends string,
QueryParams extends Record<string, string> = {}
>(config: TypedRoute<Path, QueryParams>) {
return config;
}
const routes = [
createRoute({
path: 'results/:id/foo/:bar'
}),
createRoute({
path: 'home',
children: [
createRoute({
path: 'bar',
children: [
createRoute({ path: 'baz' })
]
}),
],
}),
]
My current task involves creating a type called ExtractRoutePaths that can recursively retrieve all feasible paths:
type ExtractRoutePaths<T extends readonly TypedRoute<any, any>[]> =
T extends readonly []
? never
: T extends readonly [infer First, ...infer Rest]
? First extends TypedRoute<infer P, any>
? First extends { children: infer C }
? C extends readonly TypedRoute<any, any>[]
? `{P}` | ExtractRoutePaths<C, `${P}/`> | ExtractRoutePaths<Rest extends readonly TypedRoute<any, any>[] ? Rest : never>
: `${P}` | ExtractRoutePaths<Rest extends readonly TypedRoute<any, any>[] ? Rest : never>
: `${P}` | ExtractRoutePaths<Rest extends readonly TypedRoute<any, any>[] ? Rest : never>
: ExtractRoutePaths<Rest extends readonly TypedRoute<any, any>[] ? Rest : never>
: never;
I am aiming for the following Routes:
results/:id/foo/:bar | home | home/bar | home/bar/baz
If there are any errors in my approach, how can I modify this recursive type to correctly extract all possible paths, including nested ones?