diff --git a/__tests__/warnings.spec.ts b/__tests__/warnings.spec.ts index 6e3c63a64..a188219a7 100644 --- a/__tests__/warnings.spec.ts +++ b/__tests__/warnings.spec.ts @@ -38,4 +38,34 @@ describe('warnings', () => { router.resolve({ path: '/p', name: 'p', params: { p: 'p' } }) expect('Path "/" was passed with params').not.toHaveBeenWarned() }) + + it('warns if an alias is missing params', async () => { + createRouter({ + history: createMemoryHistory(), + routes: [{ path: '/:p/:c', alias: ['/:p/c'], component }], + }) + expect( + 'Alias "/:p/c" and the original record: "/:p/:c" should have the exact same param named "c"' + ).toHaveBeenWarned() + }) + + it('warns if an alias has a param with the same name but different', async () => { + createRouter({ + history: createMemoryHistory(), + routes: [{ path: '/:p/:c', alias: ['/:p/:c+'], component }], + }) + expect( + 'Alias "/:p/:c+" and the original record: "/:p/:c" should have the exact same param named "c"' + ).toHaveBeenWarned() + }) + + it('warns if an alias has extra params', async () => { + createRouter({ + history: createMemoryHistory(), + routes: [{ path: '/:p/c', alias: ['/:p/:c'], component }], + }) + expect( + 'Alias "/:p/:c" and the original record: "/:p/c" should have the exact same param named "c"' + ).toHaveBeenWarned() + }) }) diff --git a/src/matcher/index.ts b/src/matcher/index.ts index 1b0d0da51..02552b74b 100644 --- a/src/matcher/index.ts +++ b/src/matcher/index.ts @@ -106,6 +106,9 @@ export function createRouterMatcher( // so we can be removed if (originalRecord) { originalRecord.alias.push(matcher) + if (__DEV__) { + checkSameParams(originalRecord, matcher) + } } else { // otherwise, the first record is the original and others are aliases originalMatcher = originalMatcher || matcher @@ -362,4 +365,29 @@ function mergeOptions(defaults: T, partialOptions: Partial): T { return options } +type ParamKey = RouteRecordMatcher['keys'][number] + +function isSameParam(a: ParamKey, b: ParamKey): boolean { + return ( + a.name === b.name && + a.optional === b.optional && + a.repeatable === b.repeatable + ) +} + +function checkSameParams(a: RouteRecordMatcher, b: RouteRecordMatcher) { + for (let key of a.keys) { + if (!b.keys.find(isSameParam.bind(null, key))) + return warn( + `Alias "${b.record.path}" and the original record: "${a.record.path}" should have the exact same param named "${key.name}"` + ) + } + for (let key of b.keys) { + if (!a.keys.find(isSameParam.bind(null, key))) + return warn( + `Alias "${b.record.path}" and the original record: "${a.record.path}" should have the exact same param named "${key.name}"` + ) + } +} + export { PathParserOptions, _PathParserOptions }