From: Eduardo San Martin Morote Date: Wed, 4 May 2022 16:55:11 +0000 (+0200) Subject: feat: add replace and refactor types to work X-Git-Tag: v4.1.0~107 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c894753136aea195314ab9d86b7dce99a25f5e12;p=thirdparty%2Fvuejs%2Frouter.git feat: add replace and refactor types to work --- diff --git a/__tests__/errors.spec.ts b/__tests__/errors.spec.ts index 3f652795..8fd0e046 100644 --- a/__tests__/errors.spec.ts +++ b/__tests__/errors.spec.ts @@ -16,7 +16,7 @@ import { RouteLocationNormalized, } from '../src/types' -const routes: RouteRecordRaw[] = [ +const routes: Readonly[] = [ { path: '/', component: components.Home }, { path: '/redirect', redirect: '/' }, { path: '/foo', component: components.Foo, name: 'Foo' }, diff --git a/__tests__/matcher/resolve.spec.ts b/__tests__/matcher/resolve.spec.ts index 8bff76ae..45362fc8 100644 --- a/__tests__/matcher/resolve.spec.ts +++ b/__tests__/matcher/resolve.spec.ts @@ -42,9 +42,11 @@ describe('RouterMatcher.resolve', () => { throw new Error('not handled') } else { // use one single record + // @ts-expect-error: One way or the other it failse if (!resolved.matched) resolved.matched = record.map(normalizeRouteRecord) // allow passing an expect.any(Array) else if (Array.isArray(resolved.matched)) + // @ts-expect-error: same as above resolved.matched = resolved.matched.map(m => ({ ...normalizeRouteRecord(m as any), aliasOf: m.aliasOf, @@ -58,6 +60,7 @@ describe('RouterMatcher.resolve', () => { const startCopy: MatcherLocation = { ...start, matched: start.matched.map(m => ({ + // @ts-expect-error: okay... ...normalizeRouteRecord(m), aliasOf: m.aliasOf, })) as MatcherLocation['matched'], diff --git a/__tests__/mount.ts b/__tests__/mount.ts index d5a45744..0fbbce14 100644 --- a/__tests__/mount.ts +++ b/__tests__/mount.ts @@ -4,17 +4,24 @@ import { routeLocationKey, routerViewLocationKey, } from '../src/injectionSymbols' +import { RouteLocationNormalized } from 'src' -export function createMockedRoute(initialValue: RouteLocationNormalizedLoose) { +export function createMockedRoute( + initialValue: RouteLocationNormalizedLoose | RouteLocationNormalized +) { const route = {} as { [k in keyof RouteLocationNormalizedLoose]: ComputedRef< RouteLocationNormalizedLoose[k] > } - const routeRef = shallowRef(initialValue) + const routeRef = shallowRef< + RouteLocationNormalized | RouteLocationNormalizedLoose + >(initialValue) - function set(newRoute: RouteLocationNormalizedLoose) { + function set( + newRoute: RouteLocationNormalizedLoose | RouteLocationNormalized + ) { routeRef.value = newRoute return nextTick() } diff --git a/__tests__/utils.ts b/__tests__/utils.ts index 7878291a..ee9dd582 100644 --- a/__tests__/utils.ts +++ b/__tests__/utils.ts @@ -17,6 +17,7 @@ import { createRouter, Router, RouterView, + RouteRecordNormalized, } from '../src' export const tick = (time?: number) => @@ -57,7 +58,7 @@ export interface RouteRecordViewLoose instances: Record enterCallbacks: Record props: Record - aliasOf: RouteRecordViewLoose | undefined + aliasOf: RouteRecordNormalized | RouteRecordViewLoose | undefined children?: RouteRecordRaw[] components: Record | null | undefined } diff --git a/src/index.ts b/src/index.ts index d1eb2d13..a972d326 100644 --- a/src/index.ts +++ b/src/index.ts @@ -69,6 +69,7 @@ export type { _RemoveUntilClosingPar, } from './types/paths' export type { RouteNamedMap } from './types/named' +export type { Config, RouterTyped } from './typedRouter' export { createRouter } from './router' export type { Router, RouterOptions, RouterScrollBehavior } from './router' diff --git a/src/location.ts b/src/location.ts index 70cfbdc8..78efa330 100644 --- a/src/location.ts +++ b/src/location.ts @@ -165,8 +165,8 @@ export function isSameRouteLocationParams( } function isSameRouteLocationParamsValue( - a: RouteParamValue | RouteParamValue[], - b: RouteParamValue | RouteParamValue[] + a: RouteParamValue | readonly RouteParamValue[], + b: RouteParamValue | readonly RouteParamValue[] ): boolean { return Array.isArray(a) ? isEquivalentArray(a, b) diff --git a/src/matcher/pathParserRanker.ts b/src/matcher/pathParserRanker.ts index f225fa7a..57dd0884 100644 --- a/src/matcher/pathParserRanker.ts +++ b/src/matcher/pathParserRanker.ts @@ -1,7 +1,7 @@ import { Token, TokenType } from './pathTokenizer' import { assign } from '../utils' -export type PathParams = Record +export type PathParams = Record /** * A param in a url like `/users/:id` @@ -241,13 +241,16 @@ export function tokensToParser( path += token.value } else if (token.type === TokenType.Param) { const { value, repeatable, optional } = token - const param: string | string[] = value in params ? params[value] : '' + const param: string | readonly string[] = + value in params ? params[value] : '' if (Array.isArray(param) && !repeatable) throw new Error( `Provided param "${value}" is an array but it is not repeatable (* or + modifiers)` ) - const text: string = Array.isArray(param) ? param.join('/') : param + const text: string = Array.isArray(param) + ? (param as string[]).join('/') + : (param as string) if (!text) { if (optional) { // if we have more than one optional param like /:a?-static and there are more segments, we don't need to diff --git a/src/router.ts b/src/router.ts index d05f3c07..faed396c 100644 --- a/src/router.ts +++ b/src/router.ts @@ -13,6 +13,7 @@ import { RouteLocationOptions, MatcherLocationRaw, RouteParams, + RouteLocationNamedRaw, } from './types' import { RouterHistory, HistoryState, NavigationType } from './history/common' import { @@ -68,6 +69,7 @@ import { routerViewLocationKey, } from './injectionSymbols' import { addDevtools } from './devtools' +import { RouteNamedMap, RouteNamedMapGeneric } from './types/named' /** * Internal type to define an ErrorHandler @@ -236,7 +238,7 @@ export interface Router { * Returns the {@link RouteLocation normalized version} of a * {@link RouteLocationRaw route location}. Also includes an `href` property * that includes any existing `base`. By default the `currentLocation` used is - * `route.currentRoute` and should only be overriden in advanced use cases. + * `route.currentRoute` and should only be overridden in advanced use cases. * * @param to - Raw route location to resolve * @param currentLocation - Optional current location to resolve against @@ -252,7 +254,14 @@ export interface Router { * * @param to - Route location to navigate to */ - push(to: RouteLocationRaw): Promise + push< + RouteMap extends RouteNamedMapGeneric = RouteNamedMap, + Name extends keyof RouteMap = keyof RouteNamedMap + >( + to: RouteNamedMapGeneric extends RouteMap + ? RouteLocationRaw + : RouteLocationNamedRaw + ): Promise /** * Programmatically navigate to a new URL by replacing the current entry in @@ -260,7 +269,15 @@ export interface Router { * * @param to - Route location to navigate to */ - replace(to: RouteLocationRaw): Promise + replace< + RouteMap extends RouteNamedMapGeneric = RouteNamedMap, + Name extends keyof RouteMap = keyof RouteNamedMap + >( + to: RouteNamedMapGeneric extends RouteMap + ? RouteLocationRaw + : RouteLocationNamedRaw + ): Promise + /** * Go back in history if possible by calling `history.back()`. Equivalent to * `router.go(-1)`. @@ -585,11 +602,11 @@ export function createRouter( } } - function push(to: RouteLocationRaw | RouteLocation) { + function push(to: RouteLocationRaw) { return pushWithRedirect(to) } - function replace(to: RouteLocationRaw | RouteLocationNormalized) { + function replace(to: RouteLocationRaw) { return push(assign(locationAsObject(to), { replace: true })) } @@ -1168,7 +1185,9 @@ export function createRouter( resolve, options, + // @ts-expect-error: FIXME: can't type this one correctly without too much hussle push, + // @ts-expect-error: same replace, go, back: () => go(-1), diff --git a/src/types/index.ts b/src/types/index.ts index 3cfc9698..fc5d7b13 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -4,7 +4,7 @@ import { Ref, ComponentPublicInstance, Component, DefineComponent } from 'vue' import { RouteRecord, RouteRecordNormalized } from '../matcher/types' import { HistoryState } from '../history/common' import { NavigationFailure } from '../errors' -import { NamedLocationMap } from './named' +import { RouteNamedMapGeneric } from './named' export { NamedLocationMap, ExtractNamedRoutes, ExtractRoutes } from './named' @@ -35,10 +35,13 @@ export type RouteParamValue = string * @internal */ export type RouteParamValueRaw = RouteParamValue | number | null | undefined -export type RouteParams = Record +export type RouteParams = Record< + string, + RouteParamValue | readonly RouteParamValue[] +> export type RouteParamsRaw = Record< string, - RouteParamValueRaw | Exclude[] + RouteParamValueRaw | readonly Exclude[] > /** @@ -68,14 +71,22 @@ export interface LocationAsName { * @internal */ export interface LocationAsRelativeRaw< - T extends keyof NamedLocationMap = keyof NamedLocationMap + RouteMap extends RouteNamedMapGeneric = RouteNamedMapGeneric, + Name extends keyof RouteMap = keyof RouteMap > { - name?: {} extends NamedLocationMap ? RouteRecordName : T - params?: {} extends NamedLocationMap ? RouteParamsRaw : NamedLocationMap[T] + name?: RouteNamedMapGeneric extends RouteMap ? RouteRecordName : Name + params?: RouteNamedMapGeneric extends RouteMap + ? RouteParamsRaw + : RouteMap[Name]['paramsRaw'] } -export interface LocationAsRelative { - params?: RouteParams +export interface LocationAsRelative< + RouteMap extends RouteNamedMapGeneric = RouteNamedMapGeneric, + Name extends keyof RouteMap = keyof RouteMap +> { + params?: RouteNamedMapGeneric extends RouteMap + ? RouteParams + : RouteMap[Name]['params'] } export interface RouteLocationOptions { @@ -100,8 +111,18 @@ export interface RouteLocationOptions { */ export type RouteLocationRaw = | string - | (RouteQueryAndHash & LocationAsPath & RouteLocationOptions) - | (RouteQueryAndHash & LocationAsRelativeRaw & RouteLocationOptions) + | RouteLocationPathRaw + | RouteLocationNamedRaw + +export type RouteLocationNamedRaw< + RouteMap extends RouteNamedMapGeneric = RouteNamedMapGeneric, + Name extends keyof RouteMap = keyof RouteMap +> = RouteQueryAndHash & + LocationAsRelativeRaw & + RouteLocationOptions + +export type RouteLocationPathRaw = + | RouteQueryAndHash & LocationAsPath & RouteLocationOptions export interface RouteLocationMatched extends RouteRecordNormalized { // components cannot be Lazy @@ -199,15 +220,14 @@ export type _RouteRecordProps = * Common properties among all kind of {@link RouteRecordRaw} * @internal */ -export interface _RouteRecordBase - extends PathParserOptions { +export interface _RouteRecordBase extends PathParserOptions { /** * Path of the record. Should start with `/` unless the record is the child of * another record. * * @example `/users/:id` matches `/users/1` as well as `/users/posva`. */ - path: Path + path: string /** * Where to redirect if the route is directly matched. The redirection happens @@ -270,8 +290,7 @@ export type RouteRecordRedirectOption = /** * Route Record defining one single component with the `component` option. */ -export interface RouteRecordSingleView - extends _RouteRecordBase { +export interface RouteRecordSingleView extends _RouteRecordBase { /** * Component to display when the URL matches this route. */ @@ -286,8 +305,7 @@ export interface RouteRecordSingleView /** * Route Record defining one single component with a nested view. */ -export interface RouteRecordSingleViewWithChildren - extends _RouteRecordBase { +export interface RouteRecordSingleViewWithChildren extends _RouteRecordBase { /** * Component to display when the URL matches this route. */ @@ -308,8 +326,7 @@ export interface RouteRecordSingleViewWithChildren /** * Route Record defining multiple named components with the `components` option. */ -export interface RouteRecordMultipleViews - extends _RouteRecordBase { +export interface RouteRecordMultipleViews extends _RouteRecordBase { /** * Components to display when the URL matches this route. Allow using named views. */ @@ -327,16 +344,14 @@ export interface RouteRecordMultipleViews /** * Route Record defining multiple named components with the `components` option and children. */ -export interface RouteRecordMultipleViewsWithChildren< - Path extends string = string -> extends _RouteRecordBase { +export interface RouteRecordMultipleViewsWithChildren extends _RouteRecordBase { /** * Components to display when the URL matches this route. Allow using named views. */ components?: Record | null | undefined component?: never - children: RouteRecordRaw[] + children: Readonly[] /** * Allow passing down params as props to the component rendered by @@ -350,19 +365,18 @@ export interface RouteRecordMultipleViewsWithChildren< * Route Record that defines a redirect. Cannot have `component` or `components` * as it is never rendered. */ -export interface RouteRecordRedirect - extends _RouteRecordBase { +export interface RouteRecordRedirect extends _RouteRecordBase { redirect: RouteRecordRedirectOption component?: never components?: never } -export type RouteRecordRaw = - | RouteRecordSingleView - | RouteRecordSingleViewWithChildren - | RouteRecordMultipleViews - | RouteRecordMultipleViewsWithChildren - | RouteRecordRedirect +export type RouteRecordRaw = + | RouteRecordSingleView + | RouteRecordSingleViewWithChildren + | RouteRecordMultipleViews + | RouteRecordMultipleViewsWithChildren + | RouteRecordRedirect /** * Initial route location where the router is. Can be used in navigation guards diff --git a/src/types/named.ts b/src/types/named.ts index ce3cf33c..9b981a31 100644 --- a/src/types/named.ts +++ b/src/types/named.ts @@ -1,6 +1,6 @@ -import type { RouteRecordRaw } from '.' +import type { RouteParams, RouteParamsRaw, RouteRecordRaw } from '.' import type { Router } from '../router' -import { JoinPath, ParamsFromPath } from './paths' +import type { JoinPath, ParamsFromPath, ParamsRawFromPath } from './paths' /** * This will flat the routes into an object with `key` === `router.name` @@ -57,13 +57,20 @@ export type RouteNamedMap< children?: infer Children } ? Path extends string - ? (Name extends string + ? (Name extends string | symbol ? { - [N in Name]: ParamsFromPath> + [N in Name]: { + // name: N + params: ParamsFromPath> + // TODO: ParamsRawFromPath + paramsRaw: ParamsRawFromPath> + path: JoinPath + } } : { // NO_NAME: 1 }) & + // Recurse children (Children extends Readonly ? RouteNamedMap> : { @@ -73,8 +80,18 @@ export type RouteNamedMap< : { // EMPTY: 1 }) & - RouteNamedMap + RouteNamedMap : never // R must be a valid route record : { // END: 1 } + +export type RouteNamedMapGeneric = Record< + string | symbol | number, + // TODO: use RouteParams, RouteParamRaw + { + params: RouteParams + paramsRaw: RouteParamsRaw + path: string + } +> diff --git a/src/types/paths.ts b/src/types/paths.ts index 4d32cfd4..5da7e49d 100644 --- a/src/types/paths.ts +++ b/src/types/paths.ts @@ -1,3 +1,5 @@ +import { RouteParams, RouteParamsRaw, RouteParamValueRaw } from '.' + /** * Extract an object of params given a path like `/users/:id`. * @@ -7,16 +9,12 @@ * ``` */ export type ParamsFromPath

= string extends P - ? PathParams // Generic version - : _ExtractParamsPath<_RemoveRegexpFromParam

> + ? RouteParams // Generic version + : _ExtractParamsPath<_RemoveRegexpFromParam

, false> -/** - * Generic possible params from a path (after parsing). - */ -export type PathParams = Record< - string, - string | readonly string[] | undefined | null -> +export type ParamsRawFromPath

= string extends P + ? RouteParamsRaw // Generic version + : _ExtractParamsPath<_RemoveRegexpFromParam

, true> /** * Possible param modifiers. @@ -56,17 +54,19 @@ type _ParamDelimiter = * * @internal */ -export type _ExtractParamsPath

= - P extends `${string}{${infer PP}}${infer Rest}` - ? (PP extends `${infer N}${_ParamModifier}` - ? PP extends `${N}${infer M}` - ? M extends _ParamModifier - ? _ParamToObject - : never +export type _ExtractParamsPath< + P extends string, + isRaw extends boolean +> = P extends `${string}{${infer PP}}${infer Rest}` + ? (PP extends `${infer N}${_ParamModifier}` + ? PP extends `${N}${infer M}` + ? M extends _ParamModifier + ? _ParamToObject : never - : _ParamToObject) & - _ExtractParamsPath - : {} + : never + : _ParamToObject) & + _ExtractParamsPath + : {} /** * Gets the possible type of a param based on its modifier M. @@ -74,17 +74,34 @@ export type _ExtractParamsPath

= * @internal */ export type _ModifierParamValue< - M extends _ParamModifier | '' = _ParamModifier | '' + M extends _ParamModifier | '' = _ParamModifier | '', + isRaw extends boolean = false > = '' extends M - ? string + ? _ParamValue : '+' extends M - ? readonly [string, ...string[]] + ? _ParamValueOneOrMore : '*' extends M - ? readonly string[] | undefined | null + ? _ParamValueZeroOrMore : '?' extends M - ? string | undefined | null + ? _ParamValueZeroOrOne : never +export type _ParamValueOneOrMore = true extends isRaw + ? readonly [string | number, ...(string | number)[]] + : readonly [string, ...string[]] + +export type _ParamValueZeroOrMore = true extends isRaw + ? readonly (string | number)[] | undefined | null + : readonly string[] | undefined | null + +export type _ParamValueZeroOrOne = true extends isRaw + ? RouteParamValueRaw + : string + +export type _ParamValue = true extends isRaw + ? string | number + : string + /** * Given a param name N and its modifier M, creates a param object for the pair. * @@ -92,13 +109,14 @@ export type _ModifierParamValue< */ export type _ParamToObject< N extends string, - M extends _ParamModifier | '' + M extends _ParamModifier | '', + isRaw extends boolean > = M extends '?' | '*' ? { - [K in N]?: _ModifierParamValue + [K in N]?: _ModifierParamValue } : { - [K in N]: _ModifierParamValue + [K in N]: _ModifierParamValue } /** diff --git a/src/utils/index.ts b/src/utils/index.ts index a961bc17..1e5576af 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,4 +1,9 @@ -import { RouteParams, RouteComponent, RouteParamsRaw } from '../types' +import { + RouteParams, + RouteComponent, + RouteParamsRaw, + RouteParamValueRaw, +} from '../types' export * from './env' @@ -16,7 +21,9 @@ export function applyToParams( for (const key in params) { const value = params[key] - newParams[key] = Array.isArray(value) ? value.map(fn) : fn(value) + newParams[key] = Array.isArray(value) + ? value.map(fn) + : fn(value as Exclude) } return newParams diff --git a/test-dts/index.d.ts b/test-dts/index.d.ts index 6c37c486..573a9fdb 100644 --- a/test-dts/index.d.ts +++ b/test-dts/index.d.ts @@ -1,4 +1,5 @@ -export * from '../dist/vue-router' +// export * from '../dist/vue-router' +export * from '../src' export function describe(_name: string, _fn: () => void): void export function expectType(value: T): void diff --git a/test-dts/namedRoutes.test-d.ts b/test-dts/namedRoutes.test-d.ts index ce187e7e..9b0d5953 100644 --- a/test-dts/namedRoutes.test-d.ts +++ b/test-dts/namedRoutes.test-d.ts @@ -1,70 +1,26 @@ import { - ExtractNamedRoutes, - Router, - ExtractRoutes, createRouter, createWebHistory, RouteRecordRaw, expectType, RouteNamedMap, + RouterTyped, + Router, + RouteLocationRaw, } from './index' import { DefineComponent } from 'vue' import { JoinPath } from 'src/types/paths' -declare const Comp: DefineComponent declare const component: DefineComponent declare const components: { default: DefineComponent } -const routes = [ - { - path: 'my-path', - name: 'test', - component: Comp, - }, - { - path: 'my-path', - name: 'my-other-path', - component: Comp, - }, - { - path: 'random', - name: 'tt', - children: [ - { - path: 'random-child', - name: 'random-child', - component: Comp, - }, - ], - }, - { - name: '1', - children: [ - { - name: '2', - children: [ - { - name: '3', - children: [{ name: '4' }, { path: '', children: [{ name: '5' }] }], - }, - ], - }, - ], - }, -] as const - -export function defineRoutes< - Path extends string, - Routes extends Readonly[]> ->(routes: Routes): Routes { - return routes -} +const routeName = Symbol() const r2 = createRouter({ history: createWebHistory(), routes: [ { path: '/users/:id', name: 'UserDetails', component }, - { path: '/no-name', /* no name */ component }, + { path: '/no-name', /* no name */ components }, { path: '/nested', name: 'nested', @@ -79,11 +35,59 @@ const r2 = createRouter({ }, ], }, + { path: ':opt?', name: 'optional', component }, + // still skipped + { path: 'other', name: routeName, component }, ], }, ] as const, }) +const methods = ['push', 'replace'] as const +for (const method of methods) { + r2.push({ name: 'UserDetails' }) + r2.replace({ name: 'UserDetails' }) + + // accepts missing params because of relative locations is valid + r2[method]({ name: 'UserDetails' }) + // @ts-expect-error: but expects a correct id + r2[method]({ name: 'UserDetails', params: {} }) + // @ts-expect-error: no invalid params + r2[method]({ name: 'UserDetails', params: { id: '2', nope: 'oops' } }) + // other options are valid + r2[method]({ name: 'UserDetails', query: { valid: 'true' }, replace: true }) + r2[method]({ name: 'UserDetails', params: { id: '2' } }) + // accepts numbers + r2[method]({ name: 'UserDetails', params: { id: 2 } }) + // @ts-expect-error: fails an null + r2[method]({ name: 'UserDetails', params: { id: null } }) + // @ts-expect-error: and undefined + r2[method]({ name: 'UserDetails', params: { id: undefined } }) + // nested params work too + r2[method]({ name: 'nested-c', params: { a: '2', c: '3' } }) + r2[method]({ name: 'optional' }) + // optional params are more flexible + r2[method]({ name: 'optional', params: {} }) + r2[method]({ name: 'optional', params: { opt: 'hey' } }) + r2[method]({ name: 'optional', params: { opt: null } }) + r2[method]({ name: 'optional', params: { opt: undefined } }) + // works with symbols too + r2[method]({ name: routeName }) + // @ts-expect-error: but not other symbols + r2[method]({ name: Symbol() }) + // any path is still valid + r2[method]('/path') + // relative push can have any of the params + r2[method]({ params: { a: 2 } }) + r2[method]({ params: {} }) + r2[method]({ params: { opt: 'hey' } }) +} + +r2.push({} as unknown as RouteLocationRaw) +r2.replace({} as unknown as RouteLocationRaw) + +// createMap(r2.options.routes, true). + function joinPath( prefix: A, path: B @@ -102,70 +106,48 @@ expectType<'/nested/:a'>(joinPath('/nested/', ':a')) expectType<'/:a'>(joinPath('/nested', '/:a')) expectType<{ - UserDetails: { id: string } - nested: {} - 'nested-a': { a: string } - 'nested-c': { a: string; c: string } + UserDetails: { params: { id: string }; path: '/users/:id' } + nested: { params: {}; path: '/nested' } + 'nested-a': { params: { a: string }; path: '/nested/:a' } + 'nested-c': { params: { a: string; c: string }; path: '/nested/:a/b/:c' } }>(createMap(r2.options.routes)) expectType<{ - UserDetails: { nope: string } + UserDetails: { params: { nope: string } } // @ts-expect-error }>(createMap(r2.options.routes)) expectType<{ - 'nested-c': { a: string; d: string } + UserDetails: { path: '/users' } // @ts-expect-error }>(createMap(r2.options.routes)) expectType<{ - nope: {} + 'nested-c': { path: '/' } + // @ts-expect-error +}>(createMap(r2.options.routes)) +expectType<{ + 'nested-c': { params: { a: string; d: string } } + // @ts-expect-error +}>(createMap(r2.options.routes)) +expectType<{ + nope: { params: {} } // @ts-expect-error }>(createMap(r2.options.routes)) -declare const typed: ExtractNamedRoutes - -typed['my-other-path'] -typed['random-child'] -typed.test -typed.tt -typed[1] -typed[2] -typed[3] -typed[4] -typed[5] -//@ts-expect-error -typed['non-existing'] - -declare module './index' { - interface NamedLocationMap { - 'my-other-path': { - id: string - } +declare module '../src' { + // declare module '../dist/vue-router' { + export interface Config { + Router: typeof r2 } } -declare const router: Router - -router.push({ - name: 'my-other-path', - params: { - id: '222', - // @ts-expect-error does not exist - nonExistent: '22', - }, -}) - -router.push({ - // @ts-expect-error location name does not exist - name: 'random-location', -}) - -const otherRouter = createRouter({ - history: {} as any, - routes: [{ path: 'e', name: 'test', component: Comp }] as const, -}) - -declare const otherRoutes: ExtractRoutes +function getTypedRouter(): RouterTyped { + return {} as any +} -otherRoutes.test +const typedRouter = getTypedRouter() +// this one is true if we comment out the line with Router: typeof r2 +// expectType(typedRouter) +expectType(typedRouter) +typedRouter.push({ name: 'UserDetails' }) // @ts-expect-error -otherRoutes.test2 +typedRouter.push({ name: 'nope' })