* @jest-environment jsdom
*/
import { RouterLink } from '../src/RouterLink'
+import { RouteQueryAndHash, MatcherLocationRaw } from '../src/types'
+import { START_LOCATION_NORMALIZED } from '../src/location'
import {
- RouteQueryAndHash,
- MatcherLocationRaw,
+ createMemoryHistory,
+ RouterOptions,
RouteLocationNormalized,
-} from '../src/types'
-import { START_LOCATION_NORMALIZED } from '../src/location'
-import { createMemoryHistory, RouterOptions } from '../src'
+ RouteLocationResolved,
+} from '../src'
import { createMockedRoute } from './mount'
import { defineComponent, PropType } from 'vue'
import { RouteRecordNormalized } from '../src/matcher/types'
records.childAlias = { aliasOf: records.child } as RouteRecordNormalized
records.childEmptyAlias.aliasOf = records.childEmpty
-type RouteLocationResolved = RouteLocationNormalized & { href: string }
-
function createLocations<
T extends Record<
string,
*/
import { RouterView } from '../src/RouterView'
import { components, RouteLocationNormalizedLoose } from './utils'
-import { RouteLocationNormalized } from '../src/types'
import { START_LOCATION_NORMALIZED } from '../src/location'
import { markRaw } from 'vue'
import { createMockedRoute } from './mount'
import { mockWarn } from 'jest-mock-warn'
import { mount } from '@vue/test-utils'
+import { RouteLocationNormalized } from '../src'
// to have autocompletion
function createRoutes<T extends Record<string, RouteLocationNormalizedLoose>>(
import fakePromise from 'faked-promise'
import { createDom, tick, noGuard, newRouter as createRouter } from '../utils'
-import { RouteRecordRaw, RouteLocationRaw } from '../../src/types'
+import { RouteRecordRaw } from '../../src/types'
+import { RouteLocationRaw } from '../../src'
const Home = { template: `<div>Home</div>` }
const Foo = { template: `<div>Foo</div>` }
import { isRouteComponent, loadRouteLocation } from '../../src/navigationGuards'
-import { RouteRecordRaw, RouteLocationRaw } from '../../src/types'
+import { RouteRecordRaw } from '../../src/types'
import { components } from '../utils'
-import { createMemoryHistory, createRouter } from '../../src'
+import { RouteLocationRaw, createMemoryHistory, createRouter } from '../../src'
import { FunctionalComponent } from 'vue'
const FunctionalHome: FunctionalComponent = () => null
createMemoryHistory,
createWebHistory,
createWebHashHistory,
+ loadRouteLocation,
+ RouteLocationRaw,
} from '../src'
import { NavigationFailureType } from '../src/errors'
import { createDom, components, tick, nextNavigation } from './utils'
-import { RouteRecordRaw, RouteLocationRaw } from '../src/types'
+import { RouteRecordRaw } from '../src/types'
import { mockWarn } from 'jest-mock-warn'
import { START_LOCATION_NORMALIZED } from '../src/location'
expect(
router.resolve(
{ params: { p: 1 } },
- router.resolve({ name: 'Param', params: { p: 2 } })
+ await loadRouteLocation(
+ router.resolve({ name: 'Param', params: { p: 2 } })
+ )
)
).toMatchObject({
name: 'Param',
MatcherLocation,
RouteComponent,
RouteRecordRaw,
- _RouteRecordProps,
} from '../src/types'
import { h, ComponentOptions } from 'vue'
import {
NavigationGuard,
RouteLocationNormalized,
} from '../src'
+import { _RouteRecordProps } from '../src/typed-routes'
export const tick = (time?: number) =>
new Promise(resolve => {
// @ts-ignore
ComponentOptionsMixin,
} from 'vue'
-import { isRouteLocation, type VueUseOptions } from './types'
import { isSameRouteLocationParams, isSameRouteRecord } from './location'
import { routerKey, routeLocationKey } from './injectionSymbols'
import { RouteRecord } from './matcher/types'
import { NavigationFailure } from './errors'
import { isArray, isBrowser, noop } from './utils'
import { warn } from './warning'
+import { isRouteLocation, type VueUseOptions } from './types'
import {
RouteLocation,
- RouteLocationNormalized,
RouteLocationRaw,
+ RouteLocationResolved,
} from './typed-routes'
export interface RouterLinkOptions {
}
export interface UseLinkDevtoolsContext {
- // TODO: loaded type ?
- route: RouteLocationNormalized & { href: string }
+ route: RouteLocationResolved
isActive: boolean
isExactActive: boolean
error: string | null
hasPrevious = true
}
- return router.resolve(
- // @ts-expect-error: FIXME: errors on the name because of typed routes
- to
- )
+ return router.resolve(to)
})
const activeRecordIndex = computed<number>(() => {
import { Router } from './router'
import { UseLinkDevtoolsContext } from './RouterLink'
import { RouterViewDevtoolsContext } from './RouterView'
-import { RouteLocationNormalized } from './types'
import { assign, isArray } from './utils'
+import { RouteLocationNormalized } from './typed-routes'
/**
* Copies a route location and removes any problematic properties that cannot be shown in devtools (e.g. Vue instances).
RouteMeta,
RouteComponent,
// RawRouteComponent,
- NavigationGuardNext,
} from './types'
// Experimental Type Safe API
RouteLocationNormalized,
RouteLocationNormalizedLoaded,
RouteLocationResolved,
- RouteLocationAsRelativePath,
+ RouteLocationAsRelative,
// route records
RouteRecordInfo,
NavigationGuardWithThis,
NavigationHookAfter,
NavigationGuardReturn,
+ NavigationGuardNext,
} from './typed-routes'
export { createRouter } from './router'
import { LocationQuery, LocationQueryRaw } from './query'
-import { RouteLocationNormalized, RouteParamValue } from './types'
+import { RouteParamValue, RouteParamsGeneric } from './types'
import { RouteRecord } from './matcher/types'
import { warn } from './warning'
import { isArray } from './utils'
}
export function isSameRouteLocationParams(
- a: RouteLocationNormalized['params'],
- b: RouteLocationNormalized['params']
+ a: RouteParamsGeneric,
+ b: RouteParamsGeneric
): boolean {
if (Object.keys(a).length !== Object.keys(b).length) return false
*/
export const START_LOCATION_NORMALIZED: RouteLocationNormalizedLoaded = {
path: '/',
- // @ts-expect-error: internal name for compatibility
name: undefined,
// TODO: could we use a symbol in the future?
params: {},
MatcherLocationRaw,
MatcherLocation,
isRouteName,
- _RouteRecordProps,
} from '../types'
import { createRouterError, ErrorTypes, MatcherError } from '../errors'
import { createRouteRecordMatcher, RouteRecordMatcher } from './pathMatcher'
import { warn } from '../warning'
import { assign, noop } from '../utils'
-import type { RouteRecordName } from '../typed-routes'
+import type { RouteRecordName, _RouteRecordProps } from '../typed-routes'
/**
* Internal RouterMatcher
addRoute: (record: RouteRecordRaw, parent?: RouteRecordMatcher) => () => void
removeRoute(matcher: RouteRecordMatcher): void
- removeRoute(name: RouteRecordName): void
+ removeRoute(name: NonNullable<RouteRecordName>): void
getRoutes: () => RouteRecordMatcher[]
- getRecordMatcher: (name: RouteRecordName) => RouteRecordMatcher | undefined
+ getRecordMatcher: (
+ name: NonNullable<RouteRecordName>
+ ) => RouteRecordMatcher | undefined
/**
* Resolves a location. Gives access to the route record that corresponds to the actual path as well as filling the corresponding params objects
: noop
}
- function removeRoute(matcherRef: RouteRecordName | RouteRecordMatcher) {
+ function removeRoute(
+ matcherRef: NonNullable<RouteRecordName> | RouteRecordMatcher
+ ) {
if (isRouteName(matcherRef)) {
const matcher = matcherMap.get(matcherRef)
if (matcher) {
-import type { NavigationGuard } from '../typed-routes'
+import type {
+ NavigationGuard,
+ NavigationGuardNextCallback,
+ _RouteRecordProps,
+} from '../typed-routes'
import {
RouteRecordMultipleViews,
_RouteRecordBase,
- _RouteRecordProps,
- NavigationGuardNextCallback,
RouteRecordRaw,
} from '../types'
import { ComponentPublicInstance } from 'vue'
import {
- NavigationGuardNext,
- NavigationGuardNextCallback,
isRouteLocation,
Lazy,
RouteComponent,
RawRouteComponent,
-
- // NOTE: Still need to use some old types while migrating
- RouteLocationRaw as RouteLocationRaw_OLD,
} from './types'
import type {
RouteLocationNormalized,
RouteLocationNormalizedLoaded,
NavigationGuard,
+ RouteLocation,
+ RouteLocationRaw,
+ NavigationGuardNext,
+ NavigationGuardNextCallback,
} from './typed-routes'
import {
return () =>
new Promise((resolve, reject) => {
const next: NavigationGuardNext = (
- valid?:
- | boolean
- // TODO: remove
- | RouteLocationRaw_OLD
- | NavigationGuardNextCallback
- | Error
+ valid?: boolean | RouteLocationRaw | NavigationGuardNextCallback | Error
) => {
if (valid === false) {
reject(
* @param route - resolved route to load
*/
export function loadRouteLocation(
- route: RouteLocationNormalized
+ route: RouteLocation | RouteLocationNormalized
): Promise<RouteLocationNormalizedLoaded> {
return route.matched.every(record => record.redirect)
? Promise.reject(new Error('Cannot load a route that redirects.'))
* @param parentName - Parent Route Record where `route` should be appended at
* @param route - Route Record to add
*/
- addRoute(parentName: RouteRecordName, route: RouteRecordRaw): () => void
+ addRoute(
+ parentName: NonNullable<RouteRecordName>,
+ route: RouteRecordRaw
+ ): () => void
/**
* Add a new {@link RouteRecordRaw | route record} to the router.
*
*
* @param name - Name of the route to check
*/
- hasRoute(name: RouteRecordName): boolean
+ hasRoute(name: NonNullable<RouteRecordName>): boolean
/**
* Get a full list of all the {@link RouteRecord | route records}.
*/
applyToParams.bind(null, decode)
function addRoute(
- parentOrRoute: RouteRecordName | RouteRecordRaw,
+ parentOrRoute: NonNullable<RouteRecordName> | RouteRecordRaw,
route?: RouteRecordRaw
) {
let parent: Parameters<(typeof matcher)['addRoute']>[1] | undefined
return matcher.addRoute(record, parent)
}
- function removeRoute(name: RouteRecordName) {
+ function removeRoute(name: NonNullable<RouteRecordName>) {
const recordMatcher = matcher.getRecordMatcher(name)
if (recordMatcher) {
matcher.removeRoute(recordMatcher)
return matcher.getRoutes().map(routeMatcher => routeMatcher.record)
}
- function hasRoute(name: RouteRecordName): boolean {
+ function hasRoute(name: NonNullable<RouteRecordName>): boolean {
return !!matcher.getRecordMatcher(name)
}
removeRoute,
hasRoute,
getRoutes,
- // @ts-expect-error: FIXME: types do not match
resolve,
options,
-import { RouteLocationNormalized, RouteLocationNormalizedLoaded } from './types'
+import type {
+ RouteLocationNormalized,
+ RouteLocationNormalizedLoaded,
+} from './typed-routes'
import { warn } from './warning'
// we use types instead of interfaces to make it work with HistoryStateValue type
ParamValueOneOrMore,
ParamValueZeroOrMore,
ParamValueZeroOrOne,
+ RouteParams,
+ RouteParamsRaw,
} from './params'
export type { RouteRecordInfo } from './route-map'
export type {
- RouteRecordName as RouteRecordName,
- _RouteLocationRaw as RouteLocationRaw,
+ RouteRecordName,
+ RouteLocationRaw,
RouteLocation,
- _RouteLocationNormalized as RouteLocationNormalized,
- _RouteLocationNormalizedLoaded as RouteLocationNormalizedLoaded,
- _RouteLocationResolved as RouteLocationResolved,
- _RouteLocationAsRelativePath as RouteLocationAsRelativePath,
- _RouteParams as RouteParams,
- _RouteParamsRaw as RouteParamsRaw,
+ RouteLocationNormalized,
+ RouteLocationNormalizedGeneric,
+ RouteLocationNormalizedLoaded,
+ RouteLocationResolved,
+ RouteLocationAsRelative,
} from './route-location'
-export type { RouteRecordRedirectOption } from './route-records'
+export type {
+ RouteRecordRedirectOption,
+ RouteRecordNameGeneric,
+ _RouteRecordProps,
+} from './route-records'
export type {
NavigationGuard,
NavigationGuardReturn,
NavigationHookAfter,
NavigationGuardWithThis,
+ NavigationGuardNext,
+ NavigationGuardNextCallback,
} from './navigation-guards'
import type { _Awaitable } from '../types/utils'
-import type { NavigationGuardNext } from '../types'
import type {
- _RouteLocationNormalizedLoaded,
- RouteLocationNormalizedTypedList,
- RouteLocationNormalizedLoadedTypedList,
- RouteLocationAsString,
- RouteLocationAsRelativeTypedList,
- RouteLocationAsPathTypedList,
- _RouteLocationNormalized,
+ RouteLocationNormalizedLoaded,
+ RouteLocationNormalized,
+ RouteLocationRaw,
} from './route-location'
-import type { _RouteMapGeneric, RouteMap } from './route-map'
+import type { TypesConfig } from '../config'
import type { NavigationFailure } from '../errors'
-
-/**
- * Return types for a Navigation Guard. Accepts a type param for the RouteMap.
- */
-type NavigationGuardReturnTyped<RouteMap extends _RouteMapGeneric> =
- | void
- | Error
- | boolean
- | RouteLocationAsString<RouteMap>
- | RouteLocationAsRelativeTypedList<RouteMap>[keyof RouteMap]
- | RouteLocationAsPathTypedList<RouteMap>[keyof RouteMap]
+import { ComponentPublicInstance } from 'vue'
/**
* Return types for a Navigation Guard. Based on `TypesConfig`
*
* @see {@link TypesConfig}
- * @see {@link NavigationGuardReturnTyped}
*/
-export type NavigationGuardReturn = NavigationGuardReturnTyped<RouteMap>
+export type NavigationGuardReturn = void | Error | boolean | RouteLocationRaw
/**
- * Typed Navigation Guard with a type parameter for `this` and another for the route map.
+ * Navigation Guard with a type parameter for `this`.
+ * @see {@link TypesConfig}
*/
-export interface NavigationGuardWithThisTyped<
- T,
- RouteMap extends _RouteMapGeneric
-> {
+export interface NavigationGuardWithThis<T> {
(
this: T,
- to: RouteLocationNormalizedTypedList<RouteMap>[keyof RouteMap],
- from: RouteLocationNormalizedLoadedTypedList<RouteMap>[keyof RouteMap],
+ to: RouteLocationNormalized,
+ from: RouteLocationNormalizedLoaded,
// intentionally not typed to make people use the return
next: NavigationGuardNext
- ): _Awaitable<NavigationGuardReturnTyped<RouteMap>>
+ ): _Awaitable<NavigationGuardReturn>
}
-/**
- * Typed Navigation Guard with a type parameter for `this`. Based on `TypesConfig`
- * @see {@link TypesConfig}
- * @see {@link NavigationGuardWithThisTyped}
- */
-export interface NavigationGuardWithThis<T>
- extends NavigationGuardWithThisTyped<T, RouteMap> {}
-
/**
* In `router.beforeResolve((to) => {})`, the `to` is typed as `RouteLocationNormalizedLoaded`, not
* `RouteLocationNormalized` like in `router.beforeEach()`. In practice it doesn't change much as users do not rely on
export interface _NavigationGuardResolved {
(
this: undefined,
- to: _RouteLocationNormalizedLoaded,
- from: _RouteLocationNormalizedLoaded,
+ to: RouteLocationNormalizedLoaded,
+ from: RouteLocationNormalizedLoaded,
// intentionally not typed to make people use the return
next: NavigationGuardNext
): _Awaitable<NavigationGuardReturn>
}
/**
- * Typed Navigation Guard. Accepts a type param for the RouteMap.
+ * Navigation Guard.
*/
-export interface NavigationGuardTyped<RouteMap extends _RouteMapGeneric> {
+export interface NavigationGuard {
(
- to: _RouteLocationNormalized,
- from: _RouteLocationNormalizedLoaded,
+ to: RouteLocationNormalized,
+ from: RouteLocationNormalizedLoaded,
// intentionally not typed to make people use the return
next: NavigationGuardNext
- ): _Awaitable<NavigationGuardReturnTyped<RouteMap>>
+ ): _Awaitable<NavigationGuardReturn>
}
/**
- * Typed Navigation Guard. Based on `TypesConfig`.
- * @see {@link TypesConfig}
- * @see {@link NavigationGuardWithThisTyped}
+ * Navigation hook triggered after a navigation is settled.
*/
-export type NavigationGuard = NavigationGuardTyped<RouteMap>
-
-/**
- * Typed Navigation Hook After. Accepts a type param for the RouteMap.
- */
-export interface NavigationHookAfterTyped<RouteMap extends _RouteMapGeneric> {
+export interface NavigationHookAfter {
(
- to: RouteLocationNormalizedTypedList<RouteMap>[keyof RouteMap],
- from: RouteLocationNormalizedLoadedTypedList<RouteMap>[keyof RouteMap],
+ to: RouteLocationNormalized,
+ from: RouteLocationNormalizedLoaded,
failure?: NavigationFailure | void
): unknown
}
/**
- * Typed Navigation Hook After. Based on `TypesConfig`.
- * @see {@link TypesConfig}
- * @see {@link NavigationHookAfterTyped}
+ * `next()` callback passed to navigation guards.
+ */
+export interface NavigationGuardNext {
+ (): void
+ (error: Error): void
+ (location: RouteLocationRaw): void
+ (valid: boolean | undefined): void
+ (cb: NavigationGuardNextCallback): void
+ /**
+ * Allows to detect if `next` isn't called in a resolved guard. Used
+ * internally in DEV mode to emit a warning. Commented out to simplify
+ * typings.
+ * @internal
+ */
+ // _called: boolean
+}
+
+/**
+ * Callback that can be passed to `next()` in `beforeRouteEnter()` guards.
*/
-export interface NavigationHookAfter
- extends NavigationHookAfterTyped<RouteMap> {}
+export type NavigationGuardNextCallback = (
+ vm: ComponentPublicInstance
+) => unknown
+import type { RouteMap } from './route-map'
+
/**
* Utility type for raw and non raw params like :id+
*
// export type ParamValueOneOrMoreRaw = [ParamValueRaw, ...ParamValueRaw[]]
// export type ParamValue = string
// export type ParamValueRaw = string | number
+
+/**
+ * Generate a type safe params for a route location. Requires the name of the route to be passed as a generic.
+ * @see {@link RouteParamsGeneric}
+ */
+export type RouteParams<Name extends keyof RouteMap = keyof RouteMap> =
+ RouteMap[Name]['params']
+
+/**
+ * Generate a type safe raw params for a route location. Requires the name of the route to be passed as a generic.
+ * @see {@link RouteParamsRaw}
+ */
+export type RouteParamsRaw<Name extends keyof RouteMap = keyof RouteMap> =
+ RouteMap[Name]['paramsRaw']
import type {
- RouteLocationNormalized,
- RouteLocationNormalizedLoaded,
RouteLocationOptions,
RouteQueryAndHash,
- RouteLocationRaw,
_RouteLocationBase,
+ RouteParamsGeneric,
+ RouteLocationMatched,
+ RouteParamsRawGeneric,
} from '../types'
import type { _LiteralUnion } from '../types/utils'
// inlining the type as it avoids code splitting issues
-import type { RouteMap, _RouteMapGeneric } from './route-map'
+import type { RouteMap, RouteMapGeneric } from './route-map'
import type { Router } from '../router'
-import type { RouteRecord } from '../matcher/types'
+import type { RouteRecord, RouteRecordNormalized } from '../matcher/types'
+import { RouteRecordNameGeneric } from './route-records'
/**
- * Possible values for a user-defined route record's name
+ * Possible values for a user-defined route record's name.
*/
-export type RouteRecordName = keyof RouteMap
+export type RouteRecordName = RouteMapGeneric extends RouteMap
+ ? RouteRecordNameGeneric
+ : keyof RouteMap
/**
- * Type safe version of the {@link RouteLocation} type.
+ * Generic version of {@link RouteLocation}. It is used when no {@link RouteMap} is provided.
+ */
+export interface RouteLocationGeneric extends _RouteLocationBase {
+ /**
+ * Array of {@link RouteRecord} containing components as they were
+ * passed when adding records. It can also contain redirect records. This
+ * can't be used directly. **This property is non-enumerable**.
+ */
+ matched: RouteRecord[]
+}
+
+/**
+ * Helper to generate a type safe version of the {@link RouteLocation} type.
* @internal
*/
export interface RouteLocationTyped<
- RouteMap extends _RouteMapGeneric,
+ RouteMap extends RouteMapGeneric,
Name extends keyof RouteMap
-> extends _RouteLocationBase {
+> extends RouteLocationGeneric {
+ // Extract is needed because keyof can produce numbers
name: Extract<Name, string | symbol>
params: RouteMap[Name]['params']
-
- /**
- * Array of {@link RouteRecord} containing components as they were
- * passed when adding records. It can also contain redirect records. This
- * can't be used directly
- */
- matched: RouteRecord[] // non-enumerable
}
/**
- * Type safe version of the {@link RouteLocation} type as a Record with all the routes.
+ * List of all possible {@link RouteLocation} indexed by the route name.
* @internal
*/
export type RouteLocationTypedList<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric
+ RouteMap extends RouteMapGeneric = RouteMapGeneric
> = { [N in keyof RouteMap]: RouteLocationTyped<RouteMap, N> }
/**
- * Helper to generate a type safe version of the `RouteLocationNormalized` type.
+ * Generic version of {@link RouteLocationNormalized} that is used when no {@link RouteMap} is provided.
+ */
+export interface RouteLocationNormalizedGeneric extends _RouteLocationBase {
+ name: RouteRecordNameGeneric
+ params: RouteParamsGeneric
+ /**
+ * Array of {@link RouteRecordNormalized}
+ */
+ matched: RouteRecordNormalized[]
+}
+
+/**
+ * Helper to generate a type safe version of the {@link RouteLocationNormalized} type.
* @internal
*/
export interface RouteLocationNormalizedTyped<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric,
+ RouteMap extends RouteMapGeneric = RouteMapGeneric,
Name extends keyof RouteMap = keyof RouteMap
-> extends RouteLocationNormalized {
+> extends RouteLocationNormalizedGeneric {
name: Extract<Name, string | symbol>
// we don't override path because it could contain params and in practice it's just not useful
params: RouteMap[Name]['params']
+
+ /**
+ * Array of {@link RouteRecordNormalized}
+ */
+ matched: RouteRecordNormalized[] // non-enumerable
}
/**
- * Helper to generate a type safe version of the `RouteLocationNormalizedLoaded` type.
+ * List of all possible {@link RouteLocationNormalized} indexed by the route name.
* @internal
*/
export type RouteLocationNormalizedTypedList<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric
+ RouteMap extends RouteMapGeneric = RouteMapGeneric
> = { [N in keyof RouteMap]: RouteLocationNormalizedTyped<RouteMap, N> }
/**
- * Helper to generate a type safe version of the `RouteLocationNormalizedLoaded` type.
+ * Generic version of {@link RouteLocationNormalizedLoaded} that is used when no {@link RouteMap} is provided.
+ */
+export interface RouteLocationNormalizedLoadedGeneric
+ extends RouteLocationNormalizedGeneric {
+ /**
+ * Array of {@link RouteLocationMatched} containing only plain components (any
+ * lazy-loaded components have been loaded and were replaced inside the
+ * `components` object) so it can be directly used to display routes. It
+ * cannot contain redirect records either. **This property is non-enumerable**.
+ */
+ matched: RouteLocationMatched[]
+}
+
+/**
+ * Helper to generate a type safe version of the {@link RouteLocationNormalizedLoaded} type.
* @internal
*/
export interface RouteLocationNormalizedLoadedTyped<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric,
+ RouteMap extends RouteMapGeneric = RouteMapGeneric,
Name extends keyof RouteMap = keyof RouteMap
-> extends RouteLocationNormalizedLoaded {
+> extends RouteLocationNormalizedLoadedGeneric {
name: Extract<Name, string | symbol>
// we don't override path because it could contain params and in practice it's just not useful
params: RouteMap[Name]['params']
}
/**
- * Helper to generate a type safe version of the {@link RouteLocationNormalizedLoaded } type.
+ * List of all possible {@link RouteLocationNormalizedLoaded} indexed by the route name.
* @internal
*/
export type RouteLocationNormalizedLoadedTypedList<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric
+ RouteMap extends RouteMapGeneric = RouteMapGeneric
> = { [N in keyof RouteMap]: RouteLocationNormalizedLoadedTyped<RouteMap, N> }
/**
- * Type safe adaptation of {@link LocationAsRelativeRaw}. Used to generate the union of all possible location.
+ * Generic version of {@link RouteLocationAsRelative}. It is used when no {@link RouteMap} is provided.
+ */
+export interface RouteLocationAsRelativeGeneric
+ extends RouteQueryAndHash,
+ RouteLocationOptions {
+ name?: RouteRecordName
+ params?: RouteParamsRawGeneric
+ /**
+ * A relative path to the current location. This property should be removed
+ */
+ path?: undefined
+}
+
+/**
+ * Helper to generate a type safe version of the {@link RouteLocationAsRelative} type.
* @internal
*/
export interface RouteLocationAsRelativeTyped<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric,
+ RouteMap extends RouteMapGeneric = RouteMapGeneric,
Name extends keyof RouteMap = keyof RouteMap
-> extends RouteQueryAndHash,
- RouteLocationOptions {
- name?: Name
+> extends RouteLocationAsRelativeGeneric {
+ name?: Extract<Name, string | symbol>
params?: RouteMap[Name]['paramsRaw']
-
- // A relative path shouldn't have a path. This is easier to check with TS
- path?: undefined
}
/**
- * Type safe adaptation of {@link LocationAsRelativeRaw}. Used to generate the union of all possible location.
+ * List of all possible {@link RouteLocationAsRelative} indexed by the route name.
* @internal
*/
export type RouteLocationAsRelativeTypedList<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric
+ RouteMap extends RouteMapGeneric = RouteMapGeneric
> = { [N in keyof RouteMap]: RouteLocationAsRelativeTyped<RouteMap, N> }
/**
- * Type safe version to auto complete the path of a route.
+ * Generic version of {@link RouteLocationAsPath}. It is used when no {@link RouteMap} is provided.
+ */
+export interface RouteLocationAsPathGeneric
+ extends RouteQueryAndHash,
+ RouteLocationOptions {
+ /**
+ * Percentage encoded pathname section of the URL.
+ */
+ path: string
+}
+
+/**
+ * Helper to generate a type safe version of the {@link RouteLocationAsPath} type.
* @internal
*/
export interface RouteLocationAsPathTyped<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric,
+ RouteMap extends RouteMapGeneric = RouteMapGeneric,
Name extends keyof RouteMap = keyof RouteMap
-> extends RouteQueryAndHash,
- RouteLocationOptions {
+> extends RouteLocationAsPathGeneric {
path: _LiteralUnion<RouteMap[Name]['path']>
// // allows to check for .path and other properties that exist in different route location types
* @internal
*/
export type RouteLocationAsPathTypedList<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric
+ RouteMap extends RouteMapGeneric = RouteMapGeneric
> = { [N in keyof RouteMap]: RouteLocationAsPathTyped<RouteMap, N> }
/**
- * Same as {@link RouteLocationAsPathTyped} but as a string literal.
- * @internal
+ * Generic version of {@link RouteLocationResolved}. It is used when no {@link RouteMap} is provided.
*/
-export type RouteLocationAsString<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric
-> = _LiteralUnion<RouteMap[keyof RouteMap]['path'], string>
+export interface RouteLocationResolvedGeneric extends RouteLocationGeneric {
+ /**
+ * Resolved `href` for the route location that will be set on the `<a href="...">`.
+ */
+ href: string
+}
/**
- * Type safe version of a resolved route location returned by `router.resolve()`.
- * @see {@link RouteLocationTyped}
+ * Helper to generate a type safe version of the {@link RouteLocationResolved} type.
* @internal
*/
export interface RouteLocationResolvedTyped<
- RouteMap extends _RouteMapGeneric,
+ RouteMap extends RouteMapGeneric,
Name extends keyof RouteMap
> extends RouteLocationTyped<RouteMap, Name> {
href: string
}
/**
- * Record of all the resolved routes.
- * @see {@link RouteLocationResolvedTyped}
+ * List of all possible {@link RouteLocationResolved} indexed by the route name.
* @internal
*/
export type RouteLocationResolvedTypedList<
- RouteMap extends _RouteMapGeneric = _RouteMapGeneric
+ RouteMap extends RouteMapGeneric = RouteMapGeneric
> = { [N in keyof RouteMap]: RouteLocationResolvedTyped<RouteMap, N> }
/**
- * Type safe versions of types that are exposed by vue-router
+ * Type safe versions of types that are exposed by vue-router. We have to use a generic check to allow for names to be `undefined` when no `RouteMap` is provided.
*/
/**
- * Type safe version of `RouteLocationNormalized`. Accepts the name of the route as a type parameter.
- * @see {@link RouteLocationNormalized}
- */
-export type _RouteLocationNormalized<
- Name extends RouteRecordName = RouteRecordName
-> = RouteLocationNormalizedTypedList<RouteMap>[Name]
-
-/**
- * Type safe version of `RouteLocationNormalizedLoaded`. Accepts the name of the route as a type parameter.
- * @see {@link RouteLocationNormalizedLoaded}
+ * {@link RouteLocationRaw} resolved using the matcher
*/
-export type _RouteLocationNormalizedLoaded<
- Name extends RouteRecordName = RouteRecordName
-> = RouteLocationNormalizedLoadedTypedList<RouteMap>[Name]
+export type RouteLocation<Name extends keyof RouteMap = keyof RouteMap> =
+ RouteMapGeneric extends RouteMap
+ ? RouteLocationGeneric
+ : RouteLocationTypedList<RouteMap>[Name]
/**
- * Type safe version of `RouteLocationAsRelative`. Accepts the name of the route as a type parameter.
- * @see {@link RouteLocationAsRelative}
+ * Similar to {@link RouteLocation} but its
+ * {@link RouteLocationNormalizedTyped.matched `matched` property} cannot contain redirect records
*/
-export type _RouteLocationAsRelativePath<
- Name extends RouteRecordName = RouteRecordName
-> = RouteLocationAsRelativeTypedList<RouteMap>[Name]
+export type RouteLocationNormalized<
+ Name extends keyof RouteMap = keyof RouteMap
+> = RouteMapGeneric extends RouteMap
+ ? RouteLocationNormalizedGeneric
+ : RouteLocationNormalizedTypedList<RouteMap>[Name]
/**
- * Type safe version of `RouteLocationResolved` (the returned route of `router.resolve()`).
- * Allows passing the name of the route to be passed as a generic.
- * @see {@link Router['resolve']}
+ * Similar to {@link RouteLocationNormalized} but its `components` do not contain any function to lazy load components.
+ * In other words, it's ready to be rendered by `<RouterView>`.
+ * @see {@link RouteLocationNormalized}
*/
-export type _RouteLocationResolved<
+export type RouteLocationNormalizedLoaded<
Name extends keyof RouteMap = keyof RouteMap
-> = RouteLocationResolvedTypedList<RouteMap>[Name]
+> = RouteMapGeneric extends RouteMap
+ ? RouteLocationNormalizedLoadedGeneric
+ : RouteLocationNormalizedLoadedTypedList<RouteMap>[Name]
/**
- * {@link RouteLocationRaw} resolved using the matcher
- * @see {@link RouteLocation}
+ * Route location relative to the current location. It accepts other properties than `path` like `params`, `query` and
+ * `hash` to conveniently change them.
*/
-export type RouteLocation<Name extends keyof RouteMap = keyof RouteMap> =
- RouteLocationTypedList<RouteMap>[Name]
+export type RouteLocationAsRelative<
+ Name extends keyof RouteMap = keyof RouteMap
+> = RouteMapGeneric extends RouteMap
+ ? RouteLocationAsRelativeGeneric
+ : RouteLocationAsRelativeTypedList<RouteMap>[Name]
/**
- * Type safe version of {@link `RouteLocationRaw`} . Allows passing the name of the route to be passed as a generic.
- * @see {@link RouteLocationRaw}
+ * Route location resolved with `router.resolve()`.
+ * @see {@link Router['resolve'] | `router.resolve()`}
*/
-export type _RouteLocationRaw<Name extends keyof RouteMap = keyof RouteMap> =
- | RouteLocationAsString<RouteMap>
- | RouteLocationAsRelativeTypedList<RouteMap>[Name]
- | RouteLocationAsPathTypedList<RouteMap>[Name]
+export type RouteLocationResolved<
+ Name extends keyof RouteMap = keyof RouteMap
+> = RouteMapGeneric extends RouteMap
+ ? RouteLocationResolvedGeneric
+ : RouteLocationResolvedTypedList<RouteMap>[Name]
/**
- * Generate a type safe params for a route location. Requires the name of the route to be passed as a generic.
- * @see {@link RouteParams}
+ * Same as {@link RouteLocationAsPathTyped} but as a string literal.
+ * @internal
*/
-export type _RouteParams<Name extends keyof RouteMap = keyof RouteMap> =
- RouteMap[Name]['params']
+export type RouteLocationAsString<
+ RouteMap extends RouteMapGeneric = RouteMapGeneric
+> = RouteMapGeneric extends RouteMap
+ ? string
+ : _LiteralUnion<RouteMap[keyof RouteMap]['path'], string>
/**
- * Generate a type safe raw params for a route location. Requires the name of the route to be passed as a generic.
- * @see {@link RouteParamsRaw}
+ * Route location that can be passed to `router.push()` and other user-facing APIs.
*/
-export type _RouteParamsRaw<Name extends keyof RouteMap = keyof RouteMap> =
- RouteMap[Name]['paramsRaw']
+export type RouteLocationRaw<Name extends keyof RouteMap = keyof RouteMap> =
+ RouteMapGeneric extends RouteMap
+ ?
+ | RouteLocationAsString
+ | RouteLocationAsRelativeGeneric
+ | RouteLocationAsPathGeneric
+ :
+ | RouteLocationAsString<RouteMap>
+ | RouteLocationAsRelativeTypedList<RouteMap>[Name]
+ | RouteLocationAsPathTypedList<RouteMap>[Name]
import type { TypesConfig } from '../config'
-import type { RouteMeta, RouteParams, RouteParamsRaw } from '../types'
+import type {
+ RouteMeta,
+ RouteParamsGeneric,
+ RouteParamsRawGeneric,
+} from '../types'
import type { RouteRecord } from '../matcher/types'
/**
* @see {@link RouteRecord}
*/
export interface RouteRecordInfo<
+ // the name cannot be nullish here as that would not allow type narrowing
Name extends string | symbol = string,
Path extends string = string,
// TODO: could probably be inferred from the Params
- ParamsRaw extends RouteParamsRaw = RouteParamsRaw,
- Params extends RouteParams = RouteParams,
+ ParamsRaw extends RouteParamsRawGeneric = RouteParamsRawGeneric,
+ Params extends RouteParamsGeneric = RouteParamsGeneric,
Meta extends RouteMeta = RouteMeta
> {
name: Name
}
/**
- * Convenience type to get the typed RouteMap or a generic one if not provided.
+ * Convenience type to get the typed RouteMap or a generic one if not provided. It is extracted from the {@link TypesConfig} if it exists, it becomes {@link RouteMapGeneric} otherwise.
*/
export type RouteMap = TypesConfig extends Record<
'RouteNamedMap',
infer RouteNamedMap
>
? RouteNamedMap
- : _RouteMapGeneric
+ : RouteMapGeneric
/**
- * Generic version of the RouteMap.
- * @internal
+ * Generic version of the `RouteMap`.
*/
-export type _RouteMapGeneric = Record<string | symbol, RouteRecordInfo>
+export type RouteMapGeneric = Record<string | symbol, RouteRecordInfo>
-import { RouteLocation, _RouteLocationRaw } from './route-location'
+import {
+ RouteLocation,
+ RouteLocationNormalized,
+ RouteLocationRaw,
+} from './route-location'
+import { RouteMap } from './route-map'
/**
* @internal
*/
export type RouteRecordRedirectOption =
- | _RouteLocationRaw
- | ((to: RouteLocation) => _RouteLocationRaw)
+ | RouteLocationRaw
+ | ((to: RouteLocation) => RouteLocationRaw)
+
+/**
+ * Possible values for a route record **after normalization**
+ */
+export type RouteRecordNameGeneric = string | symbol | undefined
+
+/**
+ * @internal
+ */
+export type _RouteRecordProps<Name extends keyof RouteMap = keyof RouteMap> =
+ | boolean
+ | Record<string, any>
+ | ((to: RouteLocationNormalized<Name>) => Record<string, any>)
-import { LocationQuery, LocationQueryRaw } from '../query'
-import { PathParserOptions } from '../matcher'
-import { Ref, ComponentPublicInstance, Component, DefineComponent } from 'vue'
-import { RouteRecord, RouteRecordNormalized } from '../matcher/types'
-import { HistoryState } from '../history/common'
-import { NavigationFailure } from '../errors'
+import type { LocationQuery, LocationQueryRaw } from '../query'
+import type { PathParserOptions } from '../matcher'
+import type { Ref, Component, DefineComponent } from 'vue'
+import type { RouteRecord, RouteRecordNormalized } from '../matcher/types'
+import type { HistoryState } from '../history/common'
import type {
NavigationGuardWithThis,
RouteLocation,
RouteRecordName,
RouteRecordRedirectOption,
+ _RouteRecordProps,
+ RouteRecordNameGeneric,
} from '../typed-routes'
-import { _Awaitable } from './utils'
+import type { _Awaitable } from './utils'
export type Lazy<T> = () => Promise<T>
export type Override<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U
* @internal
*/
export type RouteParamValueRaw = RouteParamValue | number | null | undefined
-export type RouteParams = Record<string, RouteParamValue | RouteParamValue[]>
-export type RouteParamsRaw = Record<
+export type RouteParamsGeneric = Record<
+ string,
+ RouteParamValue | RouteParamValue[]
+>
+export type RouteParamsRawGeneric = Record<
string,
RouteParamValueRaw | Exclude<RouteParamValueRaw, null | undefined>[]
>
* Ignored path property since we are dealing with a relative location. Only `undefined` is allowed.
*/
path?: undefined
- params?: RouteParams
+ params?: RouteParamsGeneric
}
/**
* Ignored path property since we are dealing with a relative location. Only `undefined` is allowed.
*/
path?: undefined
- params?: RouteParams
+ params?: RouteParamsGeneric
}
/**
* @internal
*/
export interface LocationAsRelativeRaw {
- name?: RouteRecordName
+ name?: RouteRecordNameGeneric
// to allow checking location.path == null
/**
* Ignored path property since we are dealing with a relative location. Only `undefined` is allowed.
*/
path?: undefined
- params?: RouteParamsRaw
+ params?: RouteParamsRawGeneric
}
/**
state?: HistoryState
}
-/**
- * User-level route location
- */
-export type RouteLocationRaw =
- | string
- | RouteLocationPathRaw
- | RouteLocationNamedRaw
-
/**
* Route Location that can infer the necessary params based on the name.
*
MatcherLocationAsPath,
RouteLocationOptions {}
-// TODO: rename in next major
+// TODO: rename in next major to RouteRecordMatched?
export interface RouteLocationMatched extends RouteRecordNormalized {
// components cannot be Lazy<RouteComponent>
components: Record<string, RouteComponent> | null | undefined
redirectedFrom: RouteLocation | undefined
}
-// matched contains resolved components
-/**
- * {@link RouteLocationRaw} with
- */
-export interface RouteLocationNormalizedLoaded extends _RouteLocationBase {
- /**
- * Array of {@link RouteLocationMatched} containing only plain components (any
- * lazy-loaded components have been loaded and were replaced inside the
- * `components` object) so it can be directly used to display routes. It
- * cannot contain redirect records either
- */
- matched: RouteLocationMatched[] // non-enumerable
-}
-
-/**
- * Similar to {@link RouteLocation} but its
- * {@link RouteLocationNormalized.matched} cannot contain redirect records
- */
-export interface RouteLocationNormalized extends _RouteLocationBase {
- /**
- * Array of {@link RouteRecordNormalized}
- */
- matched: RouteRecordNormalized[] // non-enumerable
-}
-
/**
* Allowed Component in {@link RouteLocationMatched}
*/
*/
export type RawRouteComponent = RouteComponent | Lazy<RouteComponent>
-/**
- * @internal
- */
-export type _RouteRecordProps =
- | boolean
- | Record<string, any>
- | ((to: RouteLocationNormalized) => Record<string, any>)
-
// TODO: could this be moved to matcher?
/**
* Internal type for common properties among all kind of {@link RouteRecordRaw}.
/**
* Object of decoded params extracted from the `path`.
*/
- params: RouteParams
+ params: RouteParamsGeneric
/**
* Merged `meta` properties from all the matched route records.
matched: RouteRecord[] // non-enumerable
}
-export interface NavigationGuardNext {
- (): void
- (error: Error): void
- (location: RouteLocationRaw): void
- (valid: boolean | undefined): void
- (cb: NavigationGuardNextCallback): void
- /**
- * Allows to detect if `next` isn't called in a resolved guard. Used
- * internally in DEV mode to emit a warning. Commented out to simplify
- * typings.
- * @internal
- */
- // _called: boolean
-}
-
-export type NavigationGuardNextCallback = (
- vm: ComponentPublicInstance
-) => unknown
-
-export type NavigationGuardReturn =
- | void
- | Error
- | RouteLocationRaw
- | boolean
- // FIXME: this one is only allowed in options api
- | NavigationGuardNextCallback
-
-/**
- * Navigation guard. See [Navigation
- * Guards](/guide/advanced/navigation-guards.md).
- */
-export interface NavigationGuard {
- (
- // TODO: we could maybe add extra information like replace: true/false
- to: RouteLocationNormalized,
- from: RouteLocationNormalizedLoaded,
- next: NavigationGuardNext
- // FIXME: this one shouldn't allow returning () => ...
- ): _Awaitable<NavigationGuardReturn>
-}
-
-export interface NavigationHookAfter {
- (
- to: RouteLocationNormalized,
- from: RouteLocationNormalized,
- failure?: NavigationFailure | void
- ): any
-}
-
export * from './typeGuards'
export type Mutable<T> = {
-import type { RouteLocationRaw } from '../typed-routes'
+import type { RouteLocationRaw, RouteRecordName } from '../typed-routes'
export function isRouteLocation(route: any): route is RouteLocationRaw {
return typeof route === 'string' || (route && typeof route === 'object')
}
-export function isRouteName(name: any): name is string | symbol {
+export function isRouteName(name: any): name is RouteRecordName {
return typeof name === 'string' || typeof name === 'symbol'
}
export function useRoute<Name extends keyof RouteMap = keyof RouteMap>(
_name?: Name
): RouteLocationNormalizedLoaded<Name> {
- // @ts-expect-error: FIXME: name mismatch issue
return inject(routeLocationKey)!
}
import {
- RouteParams,
+ RouteParamsGeneric,
RouteComponent,
- RouteParamsRaw,
+ RouteParamsRawGeneric,
RouteParamValueRaw,
} from '../types'
export function applyToParams(
fn: (v: string | number | null | undefined) => string,
- params: RouteParamsRaw | undefined
-): RouteParams {
- const newParams: RouteParams = {}
+ params: RouteParamsRawGeneric | undefined
+): RouteParamsGeneric {
+ const newParams: RouteParamsGeneric = {}
for (const key in params) {
const value = params[key]