Search code examples
typescriptvue.jsvuejs3vue-routervue-router4

Typescript | Vue3 - How a specific route param can return a array of strings?


Consider this build error:

src/views/IndividualProgramView.vue:18:63 - error TS2345: Argument of type 'string | string[]' is not assignable to parameter of type 'string'.
  Type 'string[]' is not assignable to type 'string'.

18 const ProgramForm = () => programStore.renderProgramExercises(route.params.program);

I'm trying to find the param in this route: /program/1 using route.params.program.

How can this ever return string[] as a type?

I am then passing this value to a function which is expecting a string:

renderProgramExercises(id: string): VNode {

How can I fix this build error.

I did the following which works but I feel that is it wrong:

renderProgramExercises(id: string | string[]): VNode {

Thank you,


Solution

  • A route parameter can only be an array when the route is configured with a repeatable parameter:

    const router = createRouter({
      routes: [
        {
          // repeatable (0 or more)      👇  param is `string | string[]` (empty string if param absent)
          path: '/programs/:program(\\d+)*', 
    
          // OR:
          // repeatable (1 or more)      👇  param is `string[]`
          path: '/programs/:program(\\d+)+',
    
          // OR:
          // non-repeatable (1)              param is `string`
          path: '/programs/:program(\\d+)',
          â‹®
        }
      ]
    })
    

    For a *-repeatable param, its type is either string if the param is absent from the URL, or string[] otherwise, so get the param value based on its type:

    const program = Array.isArray(route.params.program)
                      ? route.params.program[0]
                      : route.params.program;
    
    programStore.renderProgramExercises(program);
    

    For a +-repeatable param, assume it's always a string[], and pass the first array element:

    programStore.renderProgramExercises(route.params.program[0]);
    

    For a non-repeatable param, assume it's always a string, and use type assertion (as keyword followed by the desired type):

    programStore.renderProgramExercises(route.params.program as string);