Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow a user to configure RouteParams and RouteParamsRaw through TypesConfig #2009

Closed
jackpercy-acl opened this issue Oct 9, 2023 · 6 comments

Comments

@jackpercy-acl
Copy link

What problem is this solving

RouteParams and RouteParamsRaw both support the types being string | string[] in order to accommodate repeatable params.

This causes an annoyance in applications where repeatable params are never used and never will be used, resulting in the codebase being littered with as string or .toString().

Having just completed a Vue 3 upgrade of a large application, we now have hundreds of Typescript warnings due to this added feature.

We started to go through the process of declaring a TypesConfig type which can be used to override $route, $router, etc, but there is a lot to configure here to change all of the params to only be a string not string[]. This also will not cover usages of useRoute and useRouter as we migrate our application from the options API to the composition API as these are not part of TypesConfig.

Proposed solution

In order to not be a breaking change, support can be added to TypesConfig to make this an opt-in change for the user.

Currently, RouteParams and RouteParamsRaw are defined as:

export declare type RouteParams = Record<string, RouteParamValue | RouteParamValue[]>;

export declare type RouteParamsRaw = Record<string, RouteParamValueRaw | Exclude<RouteParamValueRaw, null | undefined>[]>;

The proposed changed would make these conditional types from TypesConfig:

export declare type RouteParams = TypesConfig extends Record<'RouteParams', infer T>
  ? T
  : Record<string, RouteParamValue | RouteParamValue[]>

export declare type RouteParamsRaw = TypesConfig extends Record<'RouteParamsRaw', infer T>
  ? T
  : Record<string, RouteParamValueRaw | Exclude<RouteParamValueRaw, null | undefined>[]>

The user is then able to configure this in their code with:

declare module 'vue-router' {
  interface TypesConfig {
    RouteParams: Record<string, string>;
    RouteParamsRaw: Record<string, string>;
  }
}

Describe alternatives you've considered

No response

@posva
Copy link
Member

posva commented Oct 9, 2023

Duplicate of #1160

@posva posva marked this as a duplicate of #1160 Oct 9, 2023
@posva posva closed this as not planned Won't fix, can't repro, duplicate, stale Oct 9, 2023
@posva
Copy link
Member

posva commented Oct 9, 2023

You should give https://github.com/posva/unplugin-vue-router a try, it automatically generates the types of the params for you 🪄

@jackpercy-acl
Copy link
Author

Yes, we are aware of this plugin - thank you though. Migrating an application to file base routing could (and would be for us) a large change.

The proposed change would be simple to implement and greatly simplify the change needed for anyone who does not need repeatable params or want/be able to use unplugin-vue-router.

@vidal7
Copy link

vidal7 commented Aug 29, 2024

I think this issue should be be reopened for people migrating large repo. I have hundred of typescript errors Argument of type 'string | string[]' is not assignable to parameter of type 'string'. and I am not ready to use unplugin-vue-router now.

For now, to get around this issue, here is what I did since we don't use useRoute yet because we are still on Options API

declare module 'vue-router' {
    interface TypesConfig {
        $route: RouteLocationNormalizedLoaded & {
            params: Record<string, string>
        };
    }
}

@posva
Copy link
Member

posva commented Aug 29, 2024

@vidal7 your issue will never change because params can be string | string[] (repeatable params). And $route being the equivalent of useRoute() (with no args), it will still be the union of all routes, among which you probably have some with params and some without. Doing the module augmentation could backfire in the future if you use repeatable params, but if you don't even use them, it's fine 👍

The safer TS alternative is doing as string where you know the cast is safe.

That being said, the original thing was eventually adressed, you can now declare your own route map manually. I'm also confident that an LLM like chat gpt can generate a valid one given the routes array

@vidal7
Copy link

vidal7 commented Aug 29, 2024

Thank you @posva for your quick feedback. For now, I am not using repeatable params because we are migrating a big repo from Vue 2.7/Vue Router 3 to Vue 3/Vue Router 4. I am aware that it might backfire in the future but I am fine with it for now.

Also, I am not willing to spread as string hundreds of time in hundreds of files.

We might sometime declare our own route map with Typed Routes but for now my main goal is to migrate and get rid of hundreds of typescript errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants