diff --git a/packages/router/src/RouterLink.ts b/packages/router/src/RouterLink.ts index e54aa0fa0..9bd9568f1 100644 --- a/packages/router/src/RouterLink.ts +++ b/packages/router/src/RouterLink.ts @@ -31,26 +31,18 @@ import { VueUseOptions, RouteLocation, RouteLocationNormalized, - RouteLocationPathRaw, - RouteLocationString, - RouteLocationNamedRaw, } 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 type { Router } from './router' -import type { RouteNamedMap, RouteStaticPathMap } from './types/named' -import type { RouterTyped } from './typedRouter' -export interface RouterLinkOptions< - Routes extends RouteLocationRaw = RouteLocationRaw -> { +export interface RouterLinkOptions { /** * Route Location the link should navigate to when clicked on. */ - to: Routes + to: RouteLocationRaw /** * Calls `router.replace` instead of `router.push`. */ @@ -58,9 +50,7 @@ export interface RouterLinkOptions< // TODO: refactor using extra options allowed in router.push. Needs RFC } -export interface RouterLinkProps< - Routes extends RouteLocationRaw = RouteLocationRaw -> extends RouterLinkOptions { +export interface RouterLinkProps extends RouterLinkOptions { /** * Whether RouterLink should not wrap its content in an `a` tag. Useful when * using `v-slot` to create a custom RouterLink @@ -261,22 +251,20 @@ export const RouterLinkImpl = /*#__PURE__*/ defineComponent({ /** * Component to render a link that triggers a navigation on click. */ -export const RouterLink: RouterLinkTyped = RouterLinkImpl as any +export const RouterLink: _RouterLinkI = RouterLinkImpl as any /** * Typed version of the `RouterLink` component. Its generic defaults to the typed router so it can be inferred * automatically for JSX. + * + * @internal */ -export interface RouterLinkTyped { +export interface _RouterLinkI { new (): { $props: AllowedComponentProps & ComponentCustomProps & VNodeProps & - RouterLinkProps< - | RouteLocationNamedRaw> - | RouteLocationString> - | RouteLocationPathRaw> - > + RouterLinkProps $slots: { default: (arg: UnwrapRef>) => VNode[] diff --git a/packages/router/src/globalExtensions.ts b/packages/router/src/globalExtensions.ts index 878ec323c..1a9404634 100644 --- a/packages/router/src/globalExtensions.ts +++ b/packages/router/src/globalExtensions.ts @@ -4,8 +4,8 @@ import type { RouteLocationNormalizedLoaded, } from './types' import { RouterView } from './RouterView' -import type { RouterLinkTyped } from './RouterLink' -import type { RouterTyped } from './typedRouter' +import { RouterLink } from './RouterLink' +import type { Router } from './router' declare module '@vue/runtime-core' { export interface ComponentCustomOptions { @@ -55,11 +55,11 @@ declare module '@vue/runtime-core' { /** * {@link Router} instance used by the application. */ - $router: RouterTyped + $router: Router } export interface GlobalComponents { RouterView: typeof RouterView - RouterLink: RouterLinkTyped + RouterLink: typeof RouterLink } } diff --git a/packages/router/src/index.ts b/packages/router/src/index.ts index c93fe522b..3a5f738a7 100644 --- a/packages/router/src/index.ts +++ b/packages/router/src/index.ts @@ -46,7 +46,6 @@ export type { RouteParamValueRaw, RouteLocationNamedRaw, RouteLocationPathRaw, - RouteLocationString, RouteLocationMatched, RouteLocationOptions, RouteRecordRedirectOption, @@ -62,26 +61,6 @@ export type { NavigationGuardWithThis, NavigationHookAfter, } from './types' -export type { - ParamsFromPath, - ParamsRawFromPath, - _StripRegex, - _RemoveUntilClosingPar, - _ExtractParamsOfPath, - _ParamExtractResult, - _ExtractModifier, - _ModifierExtracTResult, - _JoinPath, - _ParamDelimiter, - _ParamModifier, -} from './types/paths' -export type { - RouteNamedMap, - RouteStaticPathMap, - RouteNamedInfo, - _RouteRecordNamedBaseInfo, -} from './types/named' -export type { Config, RouterTyped } from './typedRouter' export { createRouter } from './router' export type { Router, RouterOptions, RouterScrollBehavior } from './router' @@ -100,9 +79,9 @@ export { } from './navigationGuards' export { RouterLink, useLink } from './RouterLink' export type { + _RouterLinkI, RouterLinkProps, UseLinkOptions, - RouterLinkTyped, } from './RouterLink' export { RouterView } from './RouterView' export type { RouterViewProps } from './RouterView' diff --git a/packages/router/src/injectionSymbols.ts b/packages/router/src/injectionSymbols.ts index e04ef294f..ad391624f 100644 --- a/packages/router/src/injectionSymbols.ts +++ b/packages/router/src/injectionSymbols.ts @@ -1,7 +1,7 @@ -import { InjectionKey, ComputedRef, Ref } from 'vue' +import type { InjectionKey, ComputedRef, Ref } from 'vue' import { RouteLocationNormalizedLoaded } from './types' import { RouteRecordNormalized } from './matcher/types' -import { RouterTyped } from './typedRouter' +import type { Router } from './router' /** * RouteRecord being rendered by the closest ancestor Router View. Used for @@ -30,9 +30,7 @@ export const viewDepthKey = Symbol( * * @internal */ -export const routerKey = Symbol( - __DEV__ ? 'router' : '' -) as InjectionKey +export const routerKey = Symbol(__DEV__ ? 'router' : '') as InjectionKey /** * Allows overriding the current route returned by `useRoute` in tests. rl diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 177693cc5..e44946c23 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -13,9 +13,6 @@ import { RouteLocationOptions, MatcherLocationRaw, RouteParams, - RouteLocationNamedRaw, - RouteLocationPathRaw, - RouteLocationString, } from './types' import { RouterHistory, HistoryState, NavigationType } from './history/common' import { @@ -71,7 +68,6 @@ import { routerViewLocationKey, } from './injectionSymbols' import { addDevtools } from './devtools' -import { RouteNamedMap, RouteStaticPathMap } from './types/named' /** * Internal type to define an ErrorHandler @@ -185,9 +181,9 @@ export interface RouterOptions extends PathParserOptions { } /** - * Router instance. **The `Options` generic is internal**. + * Router instance. */ -export interface Router { +export interface Router { /** * @internal */ @@ -199,7 +195,7 @@ export interface Router { /** * Original options object passed to create the Router */ - readonly options: Options + readonly options: RouterOptions /** * Allows turning off the listening of history events. This is a low level api for micro-frontends. @@ -256,12 +252,7 @@ export interface Router { * * @param to - Route location to navigate to */ - push( - to: - | RouteLocationNamedRaw> - | RouteLocationString> - | RouteLocationPathRaw> - ): Promise + push(to: RouteLocationRaw): Promise /** * Programmatically navigate to a new URL by replacing the current entry in @@ -269,12 +260,7 @@ export interface Router { * * @param to - Route location to navigate to */ - replace( - to: - | RouteLocationNamedRaw> - | RouteLocationString> - | RouteLocationPathRaw> - ): Promise + replace(to: RouteLocationRaw): Promise /** * Go back in history if possible by calling `history.back()`. Equivalent to @@ -373,9 +359,7 @@ export interface Router { * * @param options - {@link RouterOptions} */ -export function createRouter( - options: Options -): Router { +export function createRouter(options: RouterOptions): Router { const matcher = createRouterMatcher(options.routes, options) const parseQuery = options.parseQuery || originalParseQuery const stringifyQuery = options.stringifyQuery || originalStringifyQuery @@ -1173,7 +1157,7 @@ export function createRouter( let started: boolean | undefined const installedApps = new Set() - const router: Router = { + const router: Router = { currentRoute, listening: true, diff --git a/packages/router/src/typedRouter.ts b/packages/router/src/typedRouter.ts deleted file mode 100644 index d5cf4bc3a..000000000 --- a/packages/router/src/typedRouter.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { Router } from './router' - -/** - * Vue Router Configuration that allows to add global types for better type support. - * - * @example - * - * ```ts - * const router = createRouter({ - * // ... - * routes: [ - * // ... - * ] as const // IMPORTANT - * }) - * - * declare module 'vue-router' { - * export interface Config { - * // allow global functions to get a typed router - * Router: typeof router - * } - * } - * ``` - */ -export interface Config { - // Router: unknown -} - -export type RouterTyped = Config extends Record<'Router', infer R> ? R : Router diff --git a/packages/router/src/types/index.ts b/packages/router/src/types/index.ts index 851b4d8aa..b693aa84a 100644 --- a/packages/router/src/types/index.ts +++ b/packages/router/src/types/index.ts @@ -4,12 +4,6 @@ import { Ref, ComponentPublicInstance, Component, DefineComponent } from 'vue' import { RouteRecord, RouteRecordNormalized } from '../matcher/types' import { HistoryState } from '../history/common' import { NavigationFailure } from '../errors' -import { - RouteNamedInfo, - RouteNamedMapGeneric, - RouteStaticPathMapGeneric, -} from './named' -import { LiteralUnion } from './utils' export type Lazy = () => Promise export type Override = Pick> & U @@ -73,25 +67,16 @@ export interface MatcherLocationAsName { /** * @internal */ -export interface LocationAsRelativeRaw< - Name extends RouteRecordName = RouteRecordName, - Info extends RouteNamedInfo = RouteNamedInfo -> { - name?: Name - params?: Info extends RouteNamedInfo - ? ParamsRaw - : RouteParamsRaw +export interface LocationAsRelativeRaw { + name?: string + params?: RouteParamsRaw } /** * @internal */ -export interface MatcherLocationAsRelative< - Info extends RouteNamedInfo = RouteNamedInfo -> { - params?: Info extends RouteNamedInfo - ? Params - : RouteParams +export interface MatcherLocationAsRelative { + params?: RouteParams } /** @@ -124,59 +109,25 @@ export type RouteLocationRaw = | RouteLocationPathRaw | RouteLocationNamedRaw -/** - * Route location that can infer full path locations - * - * @internal - */ -export type RouteLocationString< - RouteMap extends RouteStaticPathMapGeneric = RouteStaticPathMapGeneric -> = RouteStaticPathMapGeneric extends RouteMap - ? string - : LiteralUnion< - { - [K in keyof RouteMap]: RouteMap[K] - }[keyof RouteMap], - string - > - /** * Route Location that can infer the necessary params based on the name. * * @internal */ -export type RouteLocationNamedRaw< - RouteMap extends RouteNamedMapGeneric = RouteNamedMapGeneric -> = RouteNamedMapGeneric extends RouteMap - ? // allows assigning a RouteLocationRaw to RouteLocationNamedRaw - RouteQueryAndHash & LocationAsRelativeRaw & RouteLocationOptions - : { - [K in Extract]: LocationAsRelativeRaw< - K, - RouteMap[K] - > - }[Extract] & - RouteQueryAndHash & - RouteLocationOptions +export interface RouteLocationNamedRaw + extends RouteQueryAndHash, + LocationAsRelativeRaw, + RouteLocationOptions {} /** * Route Location that can infer the possible paths. * * @internal */ -export type RouteLocationPathRaw< - RouteMap extends RouteStaticPathMapGeneric = RouteStaticPathMapGeneric -> = RouteStaticPathMapGeneric extends RouteMap - ? // allows assigning a RouteLocationRaw to RouteLocationPath - RouteQueryAndHash & MatcherLocationAsPath & RouteLocationOptions - : RouteQueryAndHash & - RouteLocationOptions & - MatcherLocationAsPath< - LiteralUnion< - { [K in keyof RouteMap]: RouteMap[K] }[keyof RouteMap], - string - > - > +export interface RouteLocationPathRaw + extends RouteQueryAndHash, + MatcherLocationAsPath, + RouteLocationOptions {} export interface RouteLocationMatched extends RouteRecordNormalized { // components cannot be Lazy diff --git a/packages/router/src/types/named.ts b/packages/router/src/types/named.ts deleted file mode 100644 index d76ab3098..000000000 --- a/packages/router/src/types/named.ts +++ /dev/null @@ -1,122 +0,0 @@ -import type { - RouteParams, - RouteParamsRaw, - RouteRecordRaw, - RouteRecordName, -} from '.' -import type { _JoinPath, ParamsFromPath, ParamsRawFromPath } from './paths' - -/** - * Creates a map with each named route as a properties. Each property contains the type of the params in raw and - * normalized versions as well as the raw path. - * @internal - */ -export type RouteNamedMap< - Routes extends Readonly, - Prefix extends string = '' -> = Routes extends readonly [infer R, ...infer Rest] - ? Rest extends Readonly - ? (R extends _RouteRecordNamedBaseInfo< - infer Name, - infer Path, - infer Children - > - ? (Name extends RouteRecordName - ? { - [N in Name]: { - // name: N - params: ParamsFromPath<_JoinPath> - paramsRaw: ParamsRawFromPath<_JoinPath> - path: _JoinPath - } - } - : { - // NO_NAME: 1 - }) & - // Recurse children - (Children extends Readonly - ? RouteNamedMap> - : { - // NO_CHILDREN: 1 - }) - : { - // EMPTY: 1 - }) & - RouteNamedMap - : never // R must be a valid route record - : { - // END: 1 - } - -/** - * @internal - */ -export type RouteStaticPathMap< - Routes extends Readonly, - Prefix extends string = '' -> = Routes extends readonly [infer R, ...infer Rest] - ? Rest extends Readonly - ? (R extends _RouteRecordNamedBaseInfo< - infer _Name, - infer Path, - infer Children - > - ? { - [P in Path as _JoinPath]: _JoinPath - } & (Children extends Readonly // Recurse children - ? RouteStaticPathMap> - : { - // NO_CHILDREN: 1 - }) - : never) & // R must be a valid route record - // recurse children - RouteStaticPathMap - : { - // EMPTY: 1 - } - : { - // END: 1 - } - -/** - * Important information in a Named Route Record - * @internal - */ -export interface _RouteRecordNamedBaseInfo< - Name extends RouteRecordName = RouteRecordName, // we don't care about symbols - Path extends string = string, - Children extends Readonly = Readonly -> { - name?: Name - path: Path - children?: Children -} - -/** - * Generic map of named routes from a list of route records. - * - * @internal - */ -export type RouteNamedMapGeneric = Record - -/** - * Generic map of routes paths from a list of route records. - * - * @internal - */ -export type RouteStaticPathMapGeneric = Record - -/** - * Relevant information about a named route record to deduce its params. - * - * @internal - */ -export interface RouteNamedInfo< - Path extends string = string, - Params extends RouteParams = RouteParams, - ParamsRaw extends RouteParamsRaw = RouteParamsRaw -> { - params: Params - paramsRaw: ParamsRaw - path: Path -} diff --git a/packages/router/src/types/paths.ts b/packages/router/src/types/paths.ts deleted file mode 100644 index 2f93e6821..000000000 --- a/packages/router/src/types/paths.ts +++ /dev/null @@ -1,271 +0,0 @@ -import { RouteParamValueRaw } from '.' -import { Simplify, _AlphaNumeric } from './utils' - -/** - * Extract an object of params given a path like `/users/:id`. - * - * @example - * ```ts - * type P = ParamsFromPath<'/:id/b/:c*'> // { id: string; c?: string[] } - * ``` - */ -export type ParamsFromPath

= - P extends `${string}:${string}` - ? Simplify<_ExtractParamsOfPath> - : Record - -export type ParamsRawFromPath

= - P extends `${string}:${string}` - ? Simplify<_ExtractParamsOfPath> - : Record - -/** - * Possible param modifiers. - * - * @internal - */ -export type _ParamModifier = '+' | '?' | '*' - -/** - * Characters that mark the end of a param. In reality, there is a lot more than - * this as only alphanumerical + _ are accepted as params but that is impossible - * to achieve with TS and in practice, This set should cover them all. TODO: Add - * missing characters that do not need to be encoded. - * - * @internal - */ -export type _ParamDelimiter = - | '-' - | '/' - | '%' - | ':' - | '(' - | '\\' - | ';' - | ',' - | '&' - | '!' - | "'" - | '=' - | '@' - | '[' - | ']' - | '$' - | _ParamModifier - -/** - * Given a path, extracts the possible params or \{\} when there are no params. - * - * @internal - */ -export type _ExtractParamsOfPath< - P extends string, - isRaw extends boolean -> = P extends `${string}:${infer HasParam}` - ? _ExtractParamName extends _ParamExtractResult< - infer ParamName, - infer Rest - > - ? // ParamName is delimited by something eg: /:id/b/:c - // let's first remove the regex if there is one then extract the modifier - _ExtractModifier<_StripRegex> extends _ModifierExtracTResult< - infer Modifier, - infer Rest2 - > - ? _ParamToObject & - _ExtractParamsOfPath - : never // this should never happen as the modifier can be empty - : // Nothing after the param: /:id, we are done - _ParamToObject - : { - // EMPTY: 1 - } - -/** - * Helper type to infer a param name extraction result - * @internal - */ -export interface _ParamExtractResult

{ - param: P - rest: Rest -} - -/** - * Extracts the param name from a path. Requires to strip off the starting `:` - * - * @example - * ```ts - * _ExtractParamName<'id/:b'> // 'id' - * ``` - * - * @internal - */ -type _ExtractParamName< - Tail extends string, - Head extends string = '' -> = Tail extends `${_AlphaNumeric}${infer Rest}` - ? Tail extends `${infer C}${Rest}` - ? // Keep extracting other alphanumeric chars - _ExtractParamName - : never // ERR - : // end the recursion - _ParamExtractResult - -/** - * We consider a what comes after a param, e.g. For `/:id(\\d+)+/edit`, it would be `(\\d+)+/edit`. This should output - * everything after the regex while handling escaped `)`: `+/edit`. Note this type should be used with a string that - * starts with `(` as it will remove everything until the closing parenthesis `)`. - * - * @internal - */ -export type _StripRegex = - // do we have an escaped closing parenthesis? - S extends `(${infer A}\\)${infer Rest}` - ? // the actual regexp finished before, A has no escaped ) - A extends `${string})${infer Rest2}` - ? // Rebuild the rest - `${Rest2}\\)${Rest}` // job done - : // NOTE: expensive type when there are multiple custom regex. It's a good idea to avoid multiple custom regexs in paths. Only use custom regexs when necessary or cast the string type: `path: /:id(...)/rest` as '/:id/rest' - _RemoveUntilClosingPar // we keep removing - : // simple case with no escaping - S extends `(${string})${infer Rest}` - ? // extract the modifier if there is one - Rest - : // nothing to remove - S - -/** - * Helper type to infer a modifier extraction result. - * - * @internal - */ -export interface _ModifierExtracTResult< - M extends _ParamModifier | '', - Rest extends string -> { - modifier: M - rest: Rest -} - -/** - * Extracts the modifier and the rest of the path. This is meant to be used with everything after the param name, e.g., - * given a path of `/:paths(.+)+/end`, it should be given `+/end` and will split the path into `+` and `/end`. - * - * @internal - */ -export type _ExtractModifier

= - P extends `${_ParamModifier}${infer Rest}` - ? P extends `${infer M}${Rest}` - ? M extends _ParamModifier - ? _ModifierExtracTResult - : // impossible case - never - : // impossible case - never - : // No modifier present - _ModifierExtracTResult<'', P> - -/** - * Gets the possible type of a param based on its modifier M. - * - * @internal - */ -export type _ModifierParamValue< - M extends _ParamModifier | '' = _ParamModifier | '', - isRaw extends boolean = false -> = '' extends M - ? _ParamValue - : '+' extends M - ? _ParamValueOneOrMore - : '*' extends M - ? _ParamValueZeroOrMore - : '?' extends M - ? _ParamValueZeroOrOne - : never - -/** - * Utility type for raw and non raw params like :id+ - * - * @internal - */ -export type _ParamValueOneOrMore = true extends isRaw - ? readonly [string | number, ...(string | number)[]] - : readonly [string, ...string[]] - -/** - * Utility type for raw and non raw params like :id* - * - * @internal - */ -export type _ParamValueZeroOrMore = true extends isRaw - ? readonly (string | number)[] | undefined | null - : readonly string[] | undefined | null - -/** - * Utility type for raw and non raw params like :id? - * - * @internal - */ -export type _ParamValueZeroOrOne = true extends isRaw - ? RouteParamValueRaw - : string - -/** - * Utility type for raw and non raw params like :id - * - * @internal - */ -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. - * - * @internal - */ -export type _ParamToObject< - N extends string, - M extends _ParamModifier | '', - isRaw extends boolean -> = M extends '?' | '*' - ? { - [K in N]?: _ModifierParamValue - } - : { - [K in N]: _ModifierParamValue - } - -/** - * Takes the custom regex (and everything after) of a param and strips it off. Must be called with a string that starts - * with a `(` **after the parenthesis**. - * - * @example - * - `\\d+(?:inner-group\\)-end)/:rest-of-url` becomes `/:rest-of-url` - * - * @internal - */ -export type _RemoveUntilClosingPar = - // do we have an escaped closing parenthesis? - S extends `${infer A}\\)${infer Rest}` - ? // the actual regexp finished before, A has no escaped ) - A extends `${string})${infer Rest2}` - ? `${Rest2}\\)${Rest}` // job done - : _RemoveUntilClosingPar // we keep removing - : S extends `${string})${infer Rest}` - ? Rest - : never // nothing to remove, should not have been called, easier to spot bugs - -/** - * Joins a prefix and a path putting a `/` between them when necessary - * - * @internal - */ -export type _JoinPath< - Prefix extends string, - Path extends string -> = Path extends `/${string}` - ? Path - : '' extends Prefix - ? never - : `${Prefix}${Prefix extends `${string}/` ? '' : '/'}${Path}` diff --git a/packages/router/src/useApi.ts b/packages/router/src/useApi.ts index c62ed0c05..9bf578539 100644 --- a/packages/router/src/useApi.ts +++ b/packages/router/src/useApi.ts @@ -1,13 +1,13 @@ import { inject } from 'vue' import { routerKey, routeLocationKey } from './injectionSymbols' -import { RouterTyped } from './typedRouter' +import { Router } from './router' import { RouteLocationNormalizedLoaded } from './types' /** * Returns the router instance. Equivalent to using `$router` inside * templates. */ -export function useRouter(): RouterTyped { +export function useRouter(): Router { return inject(routerKey)! } diff --git a/packages/router/test-dts/components.test-d.tsx b/packages/router/test-dts/components.test-d.tsx index 880c55861..a7c952816 100644 --- a/packages/router/test-dts/components.test-d.tsx +++ b/packages/router/test-dts/components.test-d.tsx @@ -24,8 +24,6 @@ expectType() expectType() expectType() expectType() -// @ts-expect-error: non existing name -expectError() // RouterView expectType() diff --git a/packages/router/test-dts/namedRoutes.test-d.ts b/packages/router/test-dts/namedRoutes.test-d.ts deleted file mode 100644 index c563b8118..000000000 --- a/packages/router/test-dts/namedRoutes.test-d.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { - createRouter, - createWebHistory, - RouteRecordRaw, - expectType, - RouteNamedMap, - RouteLocationRaw, - _JoinPath, - useRouter, -} from './index' -import { DefineComponent } from 'vue' - -declare const component: DefineComponent -declare const components: { default: DefineComponent } - -const routeName = Symbol() - -const r2 = createRouter({ - history: createWebHistory(), - routes: [ - { path: '/', component }, - { path: '/foo', component }, - { path: '/users/:id', name: 'UserDetails', component }, - { path: '/no-name', /* no name */ components }, - { - path: '/nested', - name: 'nested', - children: [ - { - path: ':a', - name: 'nested-a', - children: [ - { - path: 'b', - children: [{ path: ':c', name: 'nested-c', component }], - }, - ], - }, - { 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 on 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() }) - // relative push can have any of the params - r2[method]({ params: { a: 2 } }) - r2[method]({ params: {} }) - r2[method]({ params: { opt: 'hey' } }) - // @ts-expect-error: but not non existent - r2[method]({ params: { fake_param: 'hey' } }) - - // routes with no params - r2[method]({ name: 'nested' }) - r2[method]({ name: 'nested', params: {} }) - // FIXME: is it possible to support this version - // @ts-expect-error: does not accept any params - r2[method]({ name: 'nested', params: { id: 2 } }) - - // paths - r2[method]({ path: '/nested' }) - r2[method]({ path: '/nested/:a/b' }) - // with an actual param - r2[method]({ path: '/nested/a/b' }) - // NOTE: we actually accept any string because of perf bottlenecks due to tuples - r2[method]({ path: '' }) - r2[method]({ path: '/nope' }) - r2[method]({ path: '/no-name?query' }) - r2[method]({ path: '/no-name#hash' }) - - r2[method]('/nested') - r2[method]('/nested/a/b') - - // NOTE: same as above - r2[method]('') - r2[method]('/nope') - r2[method]('/no-name?query') - r2[method]('/no-name#hash') -} - -// NOTE: not possible if we use the named routes as the point is to provide valid routes only -// @ts-expect-error -r2.push({} as unknown as RouteLocationRaw) -// @ts-expect-error -r2.replace({} as unknown as RouteLocationRaw) - -// createMap(r2.options.routes, true). - -function joinPath( - prefix: A, - path: B -): _JoinPath { - return '' as any -} - -function createMap>( - routes: R -): RouteNamedMap { - return {} as any -} - -expectType<'/nested/:a'>(joinPath('/nested', ':a')) -expectType<'/nested/:a'>(joinPath('/nested/', ':a')) -expectType<'/:a'>(joinPath('/nested', '/:a')) - -expectType<{ - 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: { params: { nope: string } } - // @ts-expect-error -}>(createMap(r2.options.routes)) -expectType<{ - UserDetails: { path: '/users' } - // @ts-expect-error -}>(createMap(r2.options.routes)) -expectType<{ - '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 module '../src' { -declare module '../dist/vue-router' { - export interface Config { - Router: typeof r2 - } -} - -const typedRouter = useRouter() -// 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 -typedRouter.push({ name: 'nope' }) diff --git a/packages/router/test-dts/paths.test-d.ts b/packages/router/test-dts/paths.test-d.ts deleted file mode 100644 index 13ebc812f..000000000 --- a/packages/router/test-dts/paths.test-d.ts +++ /dev/null @@ -1,141 +0,0 @@ -import type { - ParamsFromPath, - _StripRegex, - _ExtractParamsOfPath, - _RemoveUntilClosingPar, - _ExtractModifier, - _ModifierExtracTResult, -} from './' -import { expectType } from './' - -function params(_path: T): ParamsFromPath { - return {} as any -} - -// simple -expectType>(params('/static')) -expectType<{ id: string }>(params('/users/:id')) -// simulate a part of the string unknown at compilation time -expectType<{ id: string }>(params(`/${encodeURI('')}/:id`)) -expectType<{ id: readonly [string, ...string[]] }>(params('/users/:id+')) -expectType<{ id?: string | null | undefined }>(params('/users/:id?')) -expectType<{ id?: readonly string[] | null | undefined }>(params('/users/:id*')) - -expectType>(params('/hello/other/thing')) -// @ts-expect-error -expectType<{ thing: 'e' }>(params('/hello/other/thing')) - -// @ts-expect-error -expectType<{ other: string }>(params('/users/:id')) -// @ts-expect-error -expectType<{ other: string }>(params('/users/static')) - -// at beginning -expectType<{ id: string }>(params('/:id')) -expectType<{ id: readonly [string, ...string[]] }>(params('/:id+')) -expectType<{ id?: string | null | undefined }>(params('/:id?')) -expectType<{ id?: readonly string[] | null | undefined }>(params('/:id*')) - -// with trailing path -expectType<{ id: string }>(params('/users/:id-more')) -expectType<{ id: readonly [string, ...string[]] }>(params('/users/:id+-more')) -expectType<{ id?: string | null | undefined }>(params('/users/:id?-more')) -expectType<{ id?: readonly string[] | null | undefined }>( - params('/users/:id*-more') -) - -// multiple -expectType<{ id: string; b: string }>(params('/users/:id/:b')) -expectType<{ - id: readonly [string, ...string[]] - b: readonly [string, ...string[]] -}>(params('/users/:id+/:b+')) -expectType<{ id?: string | null | undefined; b?: string | null | undefined }>( - params('/users/:id?-:b?') -) -expectType<{ - id?: readonly string[] | null | undefined - b?: readonly string[] | null | undefined -}>(params('/users/:id*/:b*')) - -// custom regex -expectType<{ id: string }>(params('/users/:id(one)')) -expectType<{ id: string }>(params('/users/:id(\\d+)')) -expectType<{ id: readonly string[] }>(params('/users/:id(one)+')) -expectType<{ date: string }>(params('/users/:date(\\d{4}-\\d{2}-\\d{2})')) -expectType<{ a: string }>(params('/:a(pre-(?:\\d{0,5}\\)-end)')) - -expectType<{ - id: readonly [string, ...string[]] - b: string - c: string - d: string -}>(params('/:id(.*)+/other/:b/:c/:d')) - -// special characters -expectType<{ id: string }>(params('/:id$thing')) -expectType<{ id: string }>(params('/:id&thing')) -expectType<{ id: string }>(params('/:id!thing')) -expectType<{ id: string }>(params('/:id\\*thing')) -expectType<{ id: string }>(params('/:id\\thing')) -expectType<{ id: string }>(params("/:id'thing")) -expectType<{ id: string }>(params('/:id,thing')) -expectType<{ id: string }>(params('/:id;thing')) -expectType<{ id: string }>(params('/:id=thing')) -expectType<{ id: string }>(params('/:id@thing')) -expectType<{ id: string }>(params('/:id[thing')) -expectType<{ id: string }>(params('/:id]thing')) - -function removeUntilClosingPar( - _s: S -): _RemoveUntilClosingPar { - return '' as any -} - -expectType<''>(removeUntilClosingPar(')')) -expectType<'+'>(removeUntilClosingPar(')+')) -expectType<'more'>(removeUntilClosingPar(')more')) -expectType<''>(removeUntilClosingPar('\\w+)')) -expectType<'/more-url'>(removeUntilClosingPar('\\w+)/more-url')) -expectType<'/:p'>(removeUntilClosingPar('\\w+)/:p')) -expectType<'+'>(removeUntilClosingPar('oe)+')) -expectType<'/:p(o)'>(removeUntilClosingPar('\\w+)/:p(o)')) -expectType<'/:p(o)'>(removeUntilClosingPar('(?:no\\)?-end)/:p(o)')) -expectType<'/:p(o(?:no\\)?-end)'>( - removeUntilClosingPar('-end)/:p(o(?:no\\)?-end)') -) -expectType<':new(eg)other'>(removeUntilClosingPar('customr):new(eg)other')) -expectType<':new(eg)+other'>(removeUntilClosingPar('customr):new(eg)+other')) -expectType<'/:new(eg)+other'>(removeUntilClosingPar('customr)/:new(eg)+other')) -expectType<'?/:new(eg)+other'>( - removeUntilClosingPar('customr)?/:new(eg)+other') -) - -function stripRegex(_s: S): _StripRegex { - return '' as any -} - -expectType<'+/edit/'>(stripRegex('(\\d+)+/edit/')) -expectType<'*'>(stripRegex('(.*)*')) -expectType<'?/rest'>(stripRegex('?/rest')) -expectType<'*'>(stripRegex('*')) -expectType<'-other-stuff'>(stripRegex('-other-stuff')) -expectType<'/edit'>(stripRegex('/edit')) -expectType<'?/rest/:other(.*)*'>(stripRegex('?/rest/:other(.*)*')) -expectType<'+/edit/:other(.*)*'>(stripRegex('(\\d+)+/edit/:other(.*)*')) -expectType<'?/rest/:other(.*)/more/:b(.*)'>( - stripRegex('?/rest/:other(.*)/more/:b(.*)') -) - -function extractModifier(_s: S): _ExtractModifier { - return {} as any -} - -expectType<_ModifierExtracTResult<'', ''>>(extractModifier('')) -expectType<_ModifierExtracTResult<'', '-rest'>>(extractModifier('-rest')) -expectType<_ModifierExtracTResult<'', 'edit'>>(extractModifier('edit')) -expectType<_ModifierExtracTResult<'+', ''>>(extractModifier('+')) -expectType<_ModifierExtracTResult<'+', '/edit'>>(extractModifier('+/edit')) -expectType<_ModifierExtracTResult<'+', '/edit/:a?'>>( - extractModifier('+/edit/:a?') -)