Skip to content

Commit a8a0dcc

Browse files
Anoesjautofix-ci[bot]posva
authored
feat: automatically type useRoute() with a volar plugin (#609)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Eduardo San Martin Morote <[email protected]>
1 parent 98f2c0b commit a8a0dcc

32 files changed

+2552
-1505
lines changed

package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@
7777
"import": "./dist/data-loaders/pinia-colada.js",
7878
"require": "./dist/data-loaders/pinia-colada.cjs"
7979
},
80+
"./volar/sfc-route-blocks": {
81+
"require": "./dist/volar/sfc-route-blocks.cjs"
82+
},
83+
"./volar/sfc-typed-router": {
84+
"require": "./dist/volar/sfc-typed-router.cjs"
85+
},
8086
"./client": {
8187
"types": "./client.d.ts"
8288
}
@@ -134,13 +140,15 @@
134140
},
135141
"dependencies": {
136142
"@vue-macros/common": "3.0.0-beta.15",
143+
"@vue/language-core": "^3.0.1",
137144
"ast-walker-scope": "^0.8.1",
138145
"chokidar": "^4.0.3",
139146
"fast-glob": "^3.3.3",
140147
"json5": "^2.2.3",
141148
"local-pkg": "^1.1.1",
142149
"magic-string": "^0.30.17",
143150
"mlly": "^1.7.4",
151+
"muggle-string": "^0.4.1",
144152
"pathe": "^2.0.3",
145153
"picomatch": "^4.0.2",
146154
"scule": "^1.3.0",
@@ -197,7 +205,7 @@
197205
"vue": "^3.5.17",
198206
"vue-router": "^4.5.1",
199207
"vue-router-mock": "^1.1.0",
200-
"vue-tsc": "^2.2.10",
208+
"vue-tsc": "^3.0.1",
201209
"vuefire": "^3.2.1",
202210
"webpack": "^5.99.9",
203211
"yorkie": "^2.0.0"

playground/src/components/TestSetup.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
<script setup lang="ts">
2-
import { onBeforeRouteLeave } from 'vue-router'
2+
import { onBeforeRouteLeave, type RouteMap } from 'vue-router'
3+
4+
const route = useRoute()
5+
6+
route.name satisfies keyof RouteMap
37
48
onBeforeRouteLeave((to) => {
59
if (to.name === '/[name]') {

playground/src/pages/@[profileId].vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts" setup>
22
import type { Alias } from 'vite'
3-
const route = useRoute('/@[profileId]')
3+
const route = useRoute()
44
55
const route2 = definePage<{ thing: string; alias: Alias }>({
66
meta: {

playground/src/pages/[...path]+.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts" setup>
22
import { useRoute } from 'vue-router'
33
4-
const route = useRoute('/[...path]+')
4+
const route = useRoute()
55
</script>
66

77
<template>
@@ -11,7 +11,7 @@ const route = useRoute('/[...path]+')
1111
</main>
1212
</template>
1313

14-
<route>
14+
<route lang="json">
1515
{
1616
"props": true
1717
}

playground/src/pages/[...path].vue

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
<template>
22
<main>
33
<h1>Not Found</h1>
4-
<p>
5-
{{ $route.name === '/[...path]' && $route.params.path }} does not exist.
6-
</p>
4+
<p>{{ $route.params.path }} does not exist.</p>
75
</main>
86
</template>
97

10-
<route>
8+
<route lang="json">
119
{
1210
"props": true
1311
}

playground/src/pages/[name].vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import {
4949
onBeforeRouteUpdate,
5050
type RouteLocationNormalized,
5151
} from 'vue-router'
52+
import type { RouteNamedMap } from 'vue-router/auto-routes'
5253
5354
const thing = 'THING'
5455
@@ -90,8 +91,8 @@ if (routeLocation.name === '/[name]') {
9091
routeLocation.params.id
9192
}
9293
93-
const route = useRoute('/[name]')
94-
const anyRoute = useRoute()
94+
const route = useRoute()
95+
const anyRoute = useRoute<keyof RouteNamedMap>()
9596
if (anyRoute.name == '/articles/[id]') {
9697
console.log('anyRoute.params', anyRoute.params.id)
9798
}
@@ -133,7 +134,7 @@ definePage({
133134

134135
<template>
135136
<main>
136-
<h1>Param: {{ $route.name === '/[name]' && $route.params.name }}</h1>
137+
<h1>Param: {{ $route.params.name }}</h1>
137138
<h2>Param: {{ route.params.name }}</h2>
138139
<p v-show="false">{{ thing }}</p>
139140
<p v-if="isLoading">Loading user...</p>

playground/src/pages/articles.vue

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,39 @@
1-
<script lang="ts" setup></script>
1+
<script lang="ts" setup>
2+
import type { RouteLocationNormalizedLoaded } from 'vue-router'
3+
4+
const route = useRoute()
5+
route.name
6+
7+
// NOTE: I wonder if this helper is worth exposing in vue router
8+
function routeHasParam<
9+
Route extends RouteLocationNormalizedLoaded,
10+
Param extends keyof Exclude<Route['params'], Record<PropertyKey, never>>,
11+
>(
12+
route: Route,
13+
key: Param
14+
): route is Exclude<Route, { params: Record<PropertyKey, never> }> & {
15+
params: Record<Param, unknown>
16+
} {
17+
return key in route.params
18+
}
19+
20+
if ('id' in route.params) {
21+
// @ts-expect-error: TS limitation?
22+
route.name satisfies '/articles/[id]' | '/articles/[id]+'
23+
route.params.id satisfies string | [string, ...string[]]
24+
}
25+
26+
if (route.name !== '/articles' && route.name !== '/articles/') {
27+
route.name satisfies '/articles/[id]' | '/articles/[id]+'
28+
route.params.id satisfies string | [string, ...string[]]
29+
}
30+
31+
if (routeHasParam(route, 'id')) {
32+
route.name
33+
route.name satisfies '/articles/[id]' | '/articles/[id]+'
34+
route.params.id satisfies string | [string, ...string[]]
35+
}
36+
</script>
237

338
<template>
439
<h1>Articles</h1>

playground/src/pages/custom-name-and-path.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<route lang="json">
22
{
3-
"$schema": "https://raw.githubusercontent.com/posva/unplugin-vue-router/main/route.schema.json",
43
"name": "the most rebel",
54
"path": "/most-rebel",
65
"props": true
@@ -10,3 +9,7 @@
109
<!-- For some reason, a local link doesn't work... -->
1110

1211
<template>custom names</template>
12+
13+
<script setup lang="ts">
14+
useRoute().name satisfies 'the most rebel'
15+
</script>

playground/src/pages/deep/nesting/works/custom-name-and-path.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<route lang="json">
22
{
3-
"$schema": "https://raw.githubusercontent.com/posva/unplugin-vue-router/main/route.schema.json",
43
"name": "deep the most rebel",
54
"path": "/deep-most-rebel"
65
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<template>
2+
<RouterView name="default" />
3+
<RouterView name="a" />
4+
<RouterView name="b" />
5+
<!-- @vue-expect-error TODO: -->
6+
<RouterView name="c" />
7+
</template>

0 commit comments

Comments
 (0)