]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat: support jsx and tsx for RouterLink and RouterView
authorEduardo San Martin Morote <posva13@gmail.com>
Fri, 8 May 2020 10:09:31 +0000 (12:09 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Fri, 8 May 2020 10:09:31 +0000 (12:09 +0200)
Close #226

__tests__/mount.ts
src/RouterLink.ts
src/RouterView.ts
src/index.ts
test-dts/components.test-d.tsx [new file with mode: 0644]

index 8e460a4bc78c173bdbdf8f1210fb920bbf93ff03..1ad19cf20ec1fe9a39fb5ea57a4a27c4ef72bc74 100644 (file)
@@ -12,6 +12,7 @@ import {
   App,
   VNode,
   shallowRef,
+  ComponentOptions,
 } from 'vue'
 import { compile } from '@vue/compiler-dom'
 import * as runtimeDom from '@vue/runtime-dom'
@@ -21,7 +22,7 @@ import { routeLocationKey } from '../src/injectionSymbols'
 export interface MountOptions {
   propsData: Record<string, any>
   provide: Record<string | symbol, any>
-  components: Record<string, Component>
+  components: ComponentOptions['components']
   slots: Record<string, string>
 }
 
index 65550a4be89a09b6c685d28beeaf96b61d1f41f1..43acfc7b3dd743e42c475629d5ff285bbd7526d5 100644 (file)
@@ -6,20 +6,20 @@ import {
   computed,
   reactive,
   unref,
-  Component,
+  VNodeProps,
 } from 'vue'
 import { RouteLocationRaw, VueUseOptions, RouteLocation } from './types'
 import { isSameLocationObject, isSameRouteRecord } from './location'
 import { routerKey, routeLocationKey } from './injectionSymbols'
 import { RouteRecord } from './matcher/types'
 
-interface LinkProps {
+export interface RouterLinkProps {
   to: RouteLocationRaw
-  // TODO: refactor using extra options allowed in router.push
+  // TODO: refactor using extra options allowed in router.push. Needs RFC
   replace?: boolean
 }
 
-type UseLinkOptions = VueUseOptions<LinkProps>
+type UseLinkOptions = VueUseOptions<RouterLinkProps>
 
 // TODO: we could allow currentRoute as a prop to expose `isActive` and
 // `isExactActive` behavior should go through an RFC
@@ -85,7 +85,7 @@ export function useLink(props: UseLinkOptions) {
   }
 }
 
-export const RouterLink = (defineComponent({
+export const RouterLinkImpl = defineComponent({
   name: 'RouterLink',
   props: {
     to: {
@@ -137,7 +137,15 @@ export const RouterLink = (defineComponent({
           )
     }
   },
-}) as unknown) as Component
+})
+
+// export the public type for h/tsx inference
+// also to avoid inline import() in generated d.ts files
+export const RouterLink = (RouterLinkImpl as any) as {
+  new (): {
+    $props: VNodeProps & RouterLinkProps
+  }
+}
 
 function guardEvent(e: MouseEvent) {
   // don't redirect with control keys
index d622ed410cc637e3afddf4c740e2fccbdc221e37..91ddcb094c6e2ede7ce7e85b02353bd347ae07cc 100644 (file)
@@ -7,16 +7,22 @@ import {
   computed,
   ref,
   ComponentPublicInstance,
-  Component,
+  VNodeProps,
 } from 'vue'
-import { RouteLocationNormalizedLoaded } from './types'
+import { RouteLocationNormalizedLoaded, RouteLocationNormalized } from './types'
 import {
   matchedRouteKey,
   viewDepthKey,
   routeLocationKey,
 } from './injectionSymbols'
 
-export const RouterView = (defineComponent({
+export interface RouterViewProps {
+  name?: string
+  // allow looser type for user facing api
+  route?: RouteLocationNormalized
+}
+
+export const RouterViewImpl = defineComponent({
   name: 'RouterView',
   props: {
     name: {
@@ -97,4 +103,12 @@ export const RouterView = (defineComponent({
         : null
     }
   },
-}) as unknown) as Component
+})
+
+// export the public type for h/tsx inference
+// also to avoid inline import() in generated d.ts files
+export const RouterView = (RouterViewImpl as any) as {
+  new (): {
+    $props: VNodeProps & RouterViewProps
+  }
+}
index 3f71bb70e8e6cb159c6ed2faea0f6e8c9c91fefe..00f5554f88c7bea8e0e6caaf1b166c28982947ee 100644 (file)
@@ -44,7 +44,7 @@ export {
 export { NavigationFailureType, NavigationFailure } from './errors'
 
 export { onBeforeRouteLeave, onBeforeRouteUpdate } from './navigationGuards'
-export { RouterLink, useLink } from './RouterLink'
-export { RouterView } from './RouterView'
+export { RouterLink, useLink, RouterLinkProps } from './RouterLink'
+export { RouterView, RouterViewProps } from './RouterView'
 
 export * from './useApi'
diff --git a/test-dts/components.test-d.tsx b/test-dts/components.test-d.tsx
new file mode 100644 (file)
index 0000000..c8f58b0
--- /dev/null
@@ -0,0 +1,23 @@
+import { expectError, expectType } from 'tsd'
+import {
+  RouterLink,
+  RouterView,
+  createRouter,
+  createMemoryHistory,
+} from './index'
+
+let router = createRouter({
+  history: createMemoryHistory(),
+  routes: [],
+})
+
+// RouterLink
+expectError(<RouterLink />)
+expectType<JSX.Element>(<RouterLink to="/foo" replace />)
+expectType<JSX.Element>(<RouterLink to="/foo" />)
+expectType<JSX.Element>(<RouterLink to={{ path: '/foo' }} />)
+
+// RouterView
+expectType<JSX.Element>(<RouterView />)
+expectType<JSX.Element>(<RouterView name="foo" />)
+expectType<JSX.Element>(<RouterView route={router.currentRoute.value} />)