fix(nuxt): prevent param duplication in typedPages implementation (#31331)

This commit is contained in:
Anoesj Sadraee 2025-03-19 17:07:02 +01:00 committed by GitHub
parent f4182359f9
commit 0c5f40b57c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 45 additions and 3 deletions

View File

@ -202,9 +202,17 @@ export default defineNuxtModule({
// Avoid duplicate keys in the generated RouteNamedMap type
const absolutePagePath = joinURL(parent.path, page.path)
// @ts-expect-error TODO: either fix types upstream or figure out another
// way to add a route without a file, which must be possible
const route = addedPagePaths.has(absolutePagePath) ? parent : parent.insert(page.path, page.file)
const route = addedPagePaths.has(absolutePagePath)
? parent
: /^\//.test(page.path)
// @ts-expect-error TODO: either fix types upstream or figure out another
// way to add a route without a file, which must be possible
? rootPage.insert(page.path, page.file)
// @ts-expect-error TODO: either fix types upstream or figure out another
// way to add a route without a file, which must be possible
: parent.insert(page.path, page.file)
addedPagePaths.add(absolutePagePath)
if (page.meta) {
route.addToMeta(page.meta)

View File

@ -1,5 +1,5 @@
<template>
<div>
<!-- -->
<NuxtPage />
</div>
</template>

View File

@ -0,0 +1,13 @@
<script setup lang="ts">
definePageMeta({
name: 'param-id-view-custom',
// Deliberately passing absolute path here to test if params are not being duplicated in RouteNamedMap
path: '/param/:id()/view-custom',
})
</script>
<template>
<div>
<!-- -->
</div>
</template>

View File

@ -206,6 +206,7 @@ describe('typed router integration', () => {
it('correctly reads custom names typed in `definePageMeta`', () => {
const router = useRouter()
router.push({ name: 'some-custom-name' })
router.push({ name: 'param-id-view-custom', params: { id: 4 } })
})
it('allows typing useRoute', () => {
@ -224,6 +225,9 @@ describe('typed router integration', () => {
// @ts-expect-error this is an invalid param
navigateTo({ name: 'param-id', params: { bob: 23 } })
navigateTo({ name: 'param-id', params: { id: 4 } })
// @ts-expect-error this is an invalid param
navigateTo({ name: 'param-id-view-custom', params: { bob: 23 } })
navigateTo({ name: 'param-id-view-custom', params: { id: 4 } })
})
it('allows typing middleware', () => {

17
test/typed-router.test.ts Normal file
View File

@ -0,0 +1,17 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { x } from 'tinyexec'
import { describe, expect, it } from 'vitest'
const rootDir = fileURLToPath(new URL('./fixtures/basic-types', import.meta.url))
describe('typed router integration', () => {
it('does not duplicate params in RouteNamedMap when a child route overrides the path with an absolute path', async () => {
await x('nuxi', ['prepare', rootDir])
const typedRouterDtsFile = resolve(rootDir, '.nuxt/types/typed-router.d.ts')
const typedRouterDts = readFileSync(typedRouterDtsFile, 'utf8')
expect(typedRouterDts).toContain(`'param-id-view-custom': RouteRecordInfo<'param-id-view-custom', '/param/:id()/view-custom', { id: ParamValue<true> }, { id: ParamValue<false> }>,`)
expect(typedRouterDts).not.toContain(`'param-id-view-custom': RouteRecordInfo<'param-id-view-custom', '/param/:id()/view-custom', { id: ParamValue<true>, id: ParamValue<true> }, { id: ParamValue<false>, id: ParamValue<false> }>,`)
})
})