victorgarciaesgi / nuxt-typed-router

🚦Provide autocompletion and typecheck to Nuxt router
https://nuxt-typed-router.vercel.app
MIT License
354 stars 12 forks source link

$route.params or $typedRoute.params unknown type is problematic #125

Closed Bobakanoosh closed 10 months ago

Bobakanoosh commented 10 months ago

Describe the bug I'm trying to do the following with a nested dynamic route like /:username/:profileId:

<NuxtLink :to={ name: $routeNames.profile, params: $typedRoute.params  }>
   ....
</NuxtLink

But $typedRoute.params's default type is unknown. params then complains with:

Type 'unknown' is not assignable to type '{ username: string | number; profileId: string | number; }'.

Expected behavior It would be nice if the type inferred based on the name I gave (like how the params already does that). At a minimum, it would be nice if it was any so I could pass it without having to coalesce the type.

Screenshots N/A

Environnement infos

- Operating System: Windows_NT
- Node Version:     v18.12.1
- Nuxt Version:     3.8.1
- CLI Version:      3.9.1
- Nitro Version:    2.7.2
- Package Manager:  pnpm@8.9.0
- Builder:          -
- User Config:      devtools, modules, imports, vue, routeRules, css, googleFonts, sourcemap, nitro
- Runtime Modules:  @pinia/nuxt@0.5.1, nuxt-typed-router@3.3.3, @vueuse/nuxt@10.6.0, @unocss/nuxt@0.57.3, radix-vue/nuxt, nuxt-icon@0.6.5, @nuxtjs/google-fonts@3.0.2, @nuxt/image@1.0.0
- Build Modules:    -

Your pages folder structure

Run npx tree-node-cli {your page folder path}

pages
└── profiles
    β”œβ”€β”€ [username]
    β”‚   └── [profileId]
    β”‚       β”œβ”€β”€ index.vue
    β”œβ”€β”€ index.vue

Your nuxt.config.ts

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
    devtools: {
        enabled: true,
        timeline: {
            enabled: true,
        },
    },
    modules: [
        ["@pinia/nuxt", { autoImports: ["defineStore"] }],
        ["nuxt-typed-router", { plugin: true }],
        "@vueuse/nuxt",
        "@unocss/nuxt",
        "radix-vue/nuxt",
        "nuxt-icon",
        "@nuxtjs/google-fonts",
        "@nuxt/image",
    ],
    imports: {
        dirs: ["providers"],
    },
    vue: {
        defineModel: true,
    },
    css: ["@unocss/reset/tailwind.css"],
    googleFonts: {
        families: {
            Roboto: true,
        },
    },
    sourcemap: false,
    nitro: {
        preset: "cloudflare-pages",
    },
});
victorgarciaesgi commented 10 months ago

Yeah it's normal that's it's unknown, $typedRoute and typescript can't know which route you're at unless you do if ($typedRoute.name === "xxxx") before. Solution would be to use useRoute like this.

const {params} = useRoute('xxxxx')
//             ^ typed
Bobakanoosh commented 10 months ago

What do you think about at least making it any instead of unknown? That way it can at least be passed.

victorgarciaesgi commented 10 months ago

The whole point of this module is to be typesafe, you can just use $route if you want any

Bobakanoosh commented 10 months ago

Unfortunately I get this warning:

Type 'RouteParams' is not assignable to type '{ username: string | number; profileId: string | number; }'.ts(2322)

with

:to="{ name: $routesNames.siegeUsernameProfileId, params: $route.params }" 
victorgarciaesgi commented 10 months ago

Then if you don't want type safety you can just add $route.params as any

fanckush commented 8 months ago

@victorgarciaesgi

Yeah it's normal that's it's unknown, $typedRoute and typescript can't know which route you're at unless you do if ($typedRoute.name === "xxxx") before. Solution would be to use useRoute like this.

const {params} = useRoute('xxxxx')
//             ^ typed

is doing the following inside the page products/[slug].vue without the the if check safe?

const route = useRoute('products-slug')

if it is, would there be a build-time way to figure out in which pages/.. useRoute is used and based on that automatically infer the route name?

I understand how this is impossible to determine at built time within other components but route components should work