From 55bf04ed8baab3fcaabfa007e3959a8e13283626 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Thu, 7 Jul 2022 11:27:52 +0200 Subject: [PATCH] feat(types): typed useLink() --- playground/src/App.vue | 12 ++++++- playground/typed-router.d.ts | 3 ++ src/core/context.ts | 3 ++ src/index.ts | 6 +++- src/typeExtensions/RouterLink.ts | 56 ++++++++++++++++++++++++++++---- 5 files changed, 71 insertions(+), 9 deletions(-) diff --git a/playground/src/App.vue b/playground/src/App.vue index f6e21eec1..a89ad743b 100644 --- a/playground/src/App.vue +++ b/playground/src/App.vue @@ -1,11 +1,21 @@ diff --git a/playground/typed-router.d.ts b/playground/typed-router.d.ts index eae2e55c7..5428d2e3e 100644 --- a/playground/typed-router.d.ts +++ b/playground/typed-router.d.ts @@ -15,6 +15,7 @@ import type { ParamValueOneOrMore, ParamValueZeroOrMore, ParamValueZeroOrOne, + UseLinkFnTyped, } from 'unplugin-vue-router' declare module '@vue-router/routes' { @@ -68,6 +69,8 @@ declare module '@vue-router' { export function useRouter(): RouterTyped export function useRoute(name?: Name): RouteLocationNormalizedLoadedTypedList[Name] + export const useLink: UseLinkFnTyped + export function onBeforeRouteLeave(guard: NavigationGuard): void export function onBeforeRouteUpdate(guard: NavigationGuard): void } diff --git a/src/core/context.ts b/src/core/context.ts index 5bb31c4c0..4b79d2742 100644 --- a/src/core/context.ts +++ b/src/core/context.ts @@ -146,6 +146,7 @@ import type { ParamValueOneOrMore, ParamValueZeroOrMore, ParamValueZeroOrOne, + UseLinkFnTyped, } from 'unplugin-vue-router' declare module '${MODULE_ROUTES_PATH}' { @@ -176,6 +177,8 @@ declare module '${MODULE_VUE_ROUTER}' { export function useRouter(): RouterTyped export function useRoute(name?: Name): RouteLocationNormalizedLoadedTypedList[Name] + export const useLink: UseLinkFnTyped + export function onBeforeRouteLeave(guard: NavigationGuard): void export function onBeforeRouteUpdate(guard: NavigationGuard): void } diff --git a/src/index.ts b/src/index.ts index e1ebf23f3..7031d1705 100644 --- a/src/index.ts +++ b/src/index.ts @@ -95,7 +95,11 @@ export type { } from './typeExtensions/routeLocation' export type { NavigationGuard } from './typeExtensions/navigationGuards' export type { _RouterTyped } from './typeExtensions/router' -export type { RouterLinkTyped } from './typeExtensions/RouterLink' +export type { + RouterLinkTyped, + UseLinkFnTyped, + _UseLinkReturnTyped, +} from './typeExtensions/RouterLink' export type { ParamValue, ParamValueOneOrMore, diff --git a/src/typeExtensions/RouterLink.ts b/src/typeExtensions/RouterLink.ts index 382354e6d..a809f4f15 100644 --- a/src/typeExtensions/RouterLink.ts +++ b/src/typeExtensions/RouterLink.ts @@ -3,26 +3,42 @@ import type { ComponentCustomProps, VNodeProps, VNode, + ComputedRef, } from 'vue' -import type { RouterLinkProps as _RouterLinkProps } from 'vue-router' +import type { + NavigationFailure, + RouterLinkProps as _RouterLinkProps, +} from 'vue-router' import type { _RouterTyped } from './router' -// TODO: could this have a name generic to type the slot? is it +// TODO: could this have a name generic to type the slot? is it possible import { _RouteMapGeneric } from '../codegen/generateRouteMap' import { + RouteLocationAsPathTyped, RouteLocationAsPathTypedList, + RouteLocationAsRelativeTyped, RouteLocationAsRelativeTypedList, RouteLocationAsString, + RouteLocationResolvedTypedList, } from './routeLocation' -export interface RouterLinkProps - extends Omit<_RouterLinkProps, 'to'> { +/** + * Typed version of `RouterLinkProps`. + */ +export interface RouterLinkProps< + RouteMap extends _RouteMapGeneric, + Name extends keyof RouteMap = keyof RouteMap +> extends Omit<_RouterLinkProps, 'to'> { to: | RouteLocationAsString - | RouteLocationAsRelativeTypedList[keyof RouteMap] - | RouteLocationAsPathTypedList[keyof RouteMap] + | RouteLocationAsRelativeTypedList[Name] + | RouteLocationAsPathTypedList[Name] } + +/** + * Typed version of `` component. + */ export interface RouterLinkTyped { new (): { $props: AllowedComponentProps & @@ -37,4 +53,30 @@ export interface RouterLinkTyped { } } -// TODO: typed useLink() +// TODO: should be exposed by the router instead +/** + * Return type of `useLink()`. Should be exposed by the router instead. + * @internal + */ +export interface _UseLinkReturnTyped< + RouteMap extends _RouteMapGeneric, + Name extends keyof RouteMap = keyof RouteMap +> { + route: ComputedRef[Name]> + href: ComputedRef + isActive: ComputedRef + isExactActive: ComputedRef + navigate(e?: MouseEvent): Promise +} + +/** + * Typed version of `useLink()`. + */ +export interface UseLinkFnTyped { + ( + to: + | RouteLocationAsString + | RouteLocationAsRelativeTyped + | RouteLocationAsPathTyped + ): _UseLinkReturnTyped +}