vuejs / router

🚦 The official router for Vue.js
https://router.vuejs.org/
MIT License
3.74k stars 1.15k forks source link

Add support for params generic in useRoute #1160

Open fyapy opened 2 years ago

fyapy commented 2 years ago

What problem does this feature solve?

Typing of params from useRoute.

When you have function with typed arguments

const someFn = (id: string, type: ResourceType) => {}

And when you try to pass a route.params as an argument

const route = useRoute()
someFn(route.params.resourceId, route.params.type)

You will get error

Argument of type 'string | string[]' is not assignable to parameter of type 'string'. Type 'string[]' is not assignable to type 'string'.

Screenshot of problem

image

What does the proposed API look like?

type Params = {
    id: string
    type: ResourceType
}
const route = useRoute<Params>() // route.params will be typed

Pull Request

https://github.com/vuejs/vue-router-next/pull/1159

posva commented 2 years ago

This is interesting. I think we can push it a bit further the type génération for routes and the PR that @pikax sent #872 , maybe there is a way to extend the defined routes and then provide (with autocompletion) a name generic:

// given a route { path: '/users/:id', name: 'users' ... }
useRoute<'users'>() // route type with params: { id: string }
// given a route { path: '/posts/:slugs*', name: 'posts' ... }
useRoute<'posts'>() // route type with params: { slugs?: string[] }
fyapy commented 2 years ago

@posva If we have plans for a useRoute hook, may be we can add a useParams hook with generic support? Because at the moment the problem with typing params is very annoying 😞

What does the proposed API look like?

type Params = {
    id: string
    type: ResourceType
}
const params = useParams<Params>() // params with types information
posva commented 2 years ago

as mentioned in https://github.com/vuejs/router/pull/1159#issuecomment-1055275856 let's keep this in userland for the moment

import { RouteParams } from 'vue-router'
import { computed } from 'vue'

function useParams<P extends RouteParams>() {
  const route = useRoute()
  return computed(
    () => route.params as P
  )
}
posva commented 1 year ago

The current direction is leaning more towards something as automatic as possible with https://github.com/posva/unplugin-vue-router

amalitsky commented 5 months ago

Can't param types be correctly generated based on path definition? If it has * after param string, type becomes string[], otherwise it's a simple string. Am I missing something here? Thanks

posva commented 1 month ago

@amalitsky the reason is performance: https://www.youtube.com/watch?v=2hYU6HyTNdk