Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is angular type "Routes" mutable?

I want to make the routes passed to the Angular Router a constant so that I can have IntelliSense for all possible route paths:

const route = [
  { path: 'my-path', component: MenuItemsComponent },
  { path: 'my-path', component: MenuItemsComponent },
] as const;
const myRoutes = route as Routes;

Typescript says I can't do this, it throws this error:

Conversion of type 'readonly [{ readonly path: "my-path"; readonly component: typeof MenuItemsComponent; }, { readonly path: "my-path"; readonly component: typeof MenuItemsComponent; }]' to type 'Routes' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  The type 'readonly [{ readonly path: "my-path"; readonly component: typeof MenuItemsComponent; }, { readonly path: "my-path"; readonly component: typeof MenuItemsComponent; }]' is 'readonly' and cannot be assigned to the mutable type 'Routes'.

But why is Routes a mutable type? I can't understand.

Edit

To explain why i need const, is because in with consts we can do that:

type Path = typeof route[number]['path'];

So now i can restrict a variable to a path declared in the router.

like image 437
pavaj93490 Avatar asked May 25 '26 06:05

pavaj93490


1 Answers

I did a quick test on my local and your code compiles fine with Angular 11.

If your real concern is auto complete in your IDE; then you can try a conversion, like this:

const route: routes = [
  { path: 'my-path', component: MenuItemsComponent } as Route,
  { path: 'my-path', component: MenuItemsComponent } as Route,
] as const;

And I get AutoComplete in IntelliJ:

enter image description here

An alternate option might be to create your own class that extends the Route interface and use that to create your own Route interfaces.

Generally like this:

export class MyRouteClass extends Route {
  path?: string
  pathMatch?: string
  matcher?: UrlMatcher
  component?: Type<any>
  redirectTo?: string
  outlet?: string
  canActivate?: any[]
  canActivateChild?: any[]
  canDeactivate?: any[]
  canLoad?: any[]
  data?: Data
  resolve?: ResolveData
  children?: Routes
  loadChildren?: LoadChildren
  runGuardsAndResolvers?: RunGuardsAndResolvers
}

and then:

const route: routes = [
  Object.assign(new MyRouteClass(), { path: 'my-path', component: MenuItemsComponent }),
  Object.assign(new MyRouteClass(), { path: 'my-path', component: MenuItemsComponent }),
];
like image 188
JeffryHouser Avatar answered May 27 '26 01:05

JeffryHouser