diff --git a/.changeset/ninety-bears-fold.md b/.changeset/ninety-bears-fold.md new file mode 100644 index 000000000000..e89393ab634b --- /dev/null +++ b/.changeset/ninety-bears-fold.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: allow the usage of RouteId without the group segment with `resolve` \ No newline at end of file diff --git a/packages/kit/src/core/sync/write_types/index.js b/packages/kit/src/core/sync/write_types/index.js index d51c60a94442..d73042816e60 100644 --- a/packages/kit/src/core/sync/write_types/index.js +++ b/packages/kit/src/core/sync/write_types/index.js @@ -68,8 +68,8 @@ export function write_all_types(config, manifest_data) { /** @type {Set} */ const pathnames = new Set(); - /** @type {string[]} */ - const dynamic_routes = []; + /** @type {Set} */ + const dynamic_routes = new Set(); /** @type {string[]} */ const layouts = []; @@ -79,10 +79,16 @@ export function write_all_types(config, manifest_data) { const params = route.params.map((p) => `${p.name}${p.optional ? '?:' : ':'} string`); const route_type = `${s(route.id)}: { ${params.join('; ')} }`; - dynamic_routes.push(route_type); + dynamic_routes.add(route_type); const pathname = remove_group_segments(route.id); pathnames.add(`\`${replace_required_params(replace_optional_params(pathname))}\` & {}`); + + if (pathname !== route.id) { + const route_type = `${s(pathname)}: { ${params.join('; ')} }`; + + dynamic_routes.add(route_type); + } } else { const pathname = remove_group_segments(route.id); pathnames.add(s(pathname)); @@ -114,11 +120,11 @@ export function write_all_types(config, manifest_data) { fs.writeFileSync( `${types_dir}/index.d.ts`, [ - `type DynamicRoutes = {\n\t${dynamic_routes.join(';\n\t')}\n};`, + `type DynamicRoutes = {\n\t${Array.from(dynamic_routes).join(';\n\t')}\n};`, `type Layouts = {\n\t${layouts.join(';\n\t')}\n};`, // we enumerate these rather than doing `keyof Routes` so that the list is visible on hover `export type RouteId = ${manifest_data.routes.map((r) => s(r.id)).join(' | ')};`, - 'export type RouteParams = T extends keyof DynamicRoutes ? DynamicRoutes[T] : Record;', + 'export type RouteParams = T extends keyof DynamicRoutes ? DynamicRoutes[T] : Record;', 'export type LayoutParams = Layouts[T] | Record;', `export type Pathname = ${Array.from(pathnames).join(' | ')};`, 'export type ResolvedPathname = `${"" | `/${string}`}${Pathname}`;', diff --git a/packages/kit/src/core/sync/write_types/test/app-types/+page.ts b/packages/kit/src/core/sync/write_types/test/app-types/+page.ts index 09dea2ca9d96..a7b33d22e293 100644 --- a/packages/kit/src/core/sync/write_types/test/app-types/+page.ts +++ b/packages/kit/src/core/sync/write_types/test/app-types/+page.ts @@ -34,3 +34,7 @@ pathname = '/(group)/path-a'; // read `pathname` otherwise it is treated as unused pathname; + +declare let subpath_with_group: RouteParams<'/path-b/[id]/path-c'>; + +subpath_with_group.id; // okay diff --git a/packages/kit/src/core/sync/write_types/test/app-types/path-b/[id]/(group)/path-c/+page.ts b/packages/kit/src/core/sync/write_types/test/app-types/path-b/[id]/(group)/path-c/+page.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/kit/src/runtime/app/paths/types.d.ts b/packages/kit/src/runtime/app/paths/types.d.ts index 6f8a4a481fe0..85ca24597fe1 100644 --- a/packages/kit/src/runtime/app/paths/types.d.ts +++ b/packages/kit/src/runtime/app/paths/types.d.ts @@ -1,5 +1,5 @@ // @ts-ignore -import { Asset, RouteId, RouteParams, Pathname, ResolvedPathname } from '$app/types'; +import { Asset, DynamicRoutes, RouteId, RouteParams, Pathname, ResolvedPathname } from '$app/types'; /** * A string that matches [`config.kit.paths.base`](https://svelte.dev/docs/kit/configuration#paths). @@ -19,7 +19,9 @@ export let base: '' | `/${string}`; */ export let assets: '' | `https://${string}` | `http://${string}` | '/_svelte_kit_assets'; -type ResolveArgs = T extends RouteId +type ResolveArgs = T extends + | RouteId + | keyof DynamicRoutes ? RouteParams extends Record ? [route: T] : [route: T, params: RouteParams] @@ -44,7 +46,9 @@ type ResolveArgs = T extends RouteId * ``` * @since 2.26 */ -export function resolve(...args: ResolveArgs): ResolvedPathname; +export function resolve( + ...args: ResolveArgs +): ResolvedPathname; /** * Resolve the URL of an asset in your `static` directory, by prefixing it with [`config.kit.paths.assets`](https://svelte.dev/docs/kit/configuration#paths) if configured, or otherwise by prefixing it with the base path. diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 68107c9040b4..a12b93e4b723 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -2360,7 +2360,7 @@ declare module '$app/navigation' { } declare module '$app/paths' { - import type { Asset, RouteId, RouteParams, Pathname, ResolvedPathname } from '$app/types'; + import type { Asset, DynamicRoutes, RouteId, RouteParams, Pathname, ResolvedPathname } from '$app/types'; /** * A string that matches [`config.kit.paths.base`](https://svelte.dev/docs/kit/configuration#paths). * @@ -2379,7 +2379,9 @@ declare module '$app/paths' { */ export let assets: '' | `https://${string}` | `http://${string}` | '/_svelte_kit_assets'; - type ResolveArgs = T extends RouteId + type ResolveArgs = T extends + | RouteId + | keyof DynamicRoutes ? RouteParams extends Record ? [route: T] : [route: T, params: RouteParams] @@ -2404,7 +2406,9 @@ declare module '$app/paths' { * ``` * @since 2.26 */ - export function resolve(...args: ResolveArgs): ResolvedPathname; + export function resolve( + ...args: ResolveArgs + ): ResolvedPathname; /** * Resolve the URL of an asset in your `static` directory, by prefixing it with [`config.kit.paths.assets`](https://svelte.dev/docs/kit/configuration#paths) if configured, or otherwise by prefixing it with the base path.