solidjs / solid-router

A universal router for Solid inspired by Ember and React Router
MIT License
1.15k stars 147 forks source link

feat: allow readonly array as argument to useRoutes #256

Closed v-moe closed 1 year ago

v-moe commented 1 year ago

Allow readonly array as argument to useRoutes

The setup

Currently I can use a config based setup like

const routes = [
  {
    path: '/',
    component: lazy(() => import('/src/pages/Home')),
  },
  {
    path: '/test',
    component: lazy(() => import('/src/pages/Test')),
  },
  {
    path: '/new',
    component: lazy(() => import('/src/pages/New')),
  },
] satisfies Parameters<typeof useRoutes>[0]

and use it in my App component like

const App: Component = () => {
  const Routes = useRoutes(routes)
  return (
    <Router>
      <Routes />
    </Router>
  )
}

The task

I want to get a union type of all the possible paths, i.e. '/' | 'test' | 'new'. This approach obviously does not work:

type Path = (typeof routes)[number]['path'] // just string

The workaround

In order to make the above snippet work I have to add a const assertion to each element in the routes array like this:

const routes = [
  {
    path: '/',
    component: lazy(() => import('/src/pages/Home')),
  } as const,
  {
    path: '/test',
    component: lazy(() => import('/src/pages/Test')),
  } as const,
  {
    path: '/new',
    component: lazy(() => import('/src/pages/New')),
  } as const,
] satisfies Parameters<typeof useRoutes>[0]

The improvement

While the workaround works just fine it would be desirable to be able to just add the const assertion to the whole array instead like this:

const routes = [
  {
    path: '/',
    component: lazy(() => import('/src/pages/Home')),
  },
  {
    path: '/test',
    component: lazy(() => import('/src/pages/Test')),
  },
  {
    path: '/new',
    component: lazy(() => import('/src/pages/New')),
  },
] as const satisfies Parameters<typeof useRoutes>[0]

The issue

Adding as const will lead to an error since useRoutes is typed like this:

export declare const useRoutes: (routes: RouteDefinition | RouteDefinition[], base?: string) => () => JSX.Element;

The proposed solution

Allowing RouteDefinition[] to be readonly will make the const assertion on the whole array work.

ryansolid commented 1 year ago

Sure. Thanks.

v-moe commented 1 year ago

Thank you for Solid and its ecosystem! This is my first open source contribution and I am so thrilled it was for Solid!