1

Use case

Guard components using CanActivate of Angular Guard.

Sample Route

{
 path: "my-path",
 component: MyComponent,
 canActivate: [AuthGuard]
}

MyComponent as sample component

export class MyComponent {
  // Dependency required by AuthGuard to allow/deny access
  // Each component declares resources that it guards, along with access levels
  static guardedResources = [
    {"user_profile" : {"access" : "write"}},
    {"posts" : {"access" : "read"}}
  ];
}

AuthGuard code

canActivate(route: ActivatedRouteSnapshot) {
  // Component resolution happens at runtime via route.component
  
  // Common logic to read component's guardedResources and match them against
  // user's access privileges lies here
}

When I try to access the component property via route.component.guardedResources, it throws

error TS2339: Property 'guardedResources' does not exist on type 'string | Type<any>'.
      Property 'guardedResources' does not exist on type 'string'.

Doing console.log(route.component) shows my component's body on console, so I'm fairly confident that I can resolve this by typecasting route.component appropriately to get through to guardedResources.

Possible solution

Step 1 - Abstract guardedResources in a base class and override that property in derived components.

Step 2 - Typecast route.component to this base class so that guardedResources is available as a valid property.

I think I am missing some basic knowledge of Angular or TypeScript here. Could someone please point me to relevant links/docs that I could refer?

rhetonik
  • 1,818
  • 1
  • 15
  • 21

2 Answers2

0

The route.component holds the type of the component as string or Type<any>, so if you want to get the static guardedResources from it, you have to cast it to MyComponent type before that, like the following:

// To make sure that the component type is `MyComponent`
if (route.component === MyComponent) {
  // Cast the type of route.component` to the type of `MyComponent` to access its static variables:
  const guardedResources = (route.component as typeof MyComponent).guardedResources;

  // Do the other stuff here
}
Amer
  • 6,162
  • 2
  • 8
  • 34
0

There is a similar answer for this issue on this link. Another way to handle this, might be a constant handling the paths with the inner object of what you are trying to match:

 export const ROLES = {
   'my-path': {
     {'user_profile' : {'access' : 'write'}},
     {'posts': {'access' : 'read'}}
   }
 }

Then in your guard you can simply check the path of the route and do the necessary logic, without the need of casting a component.

I think it might be cleaner that way.

Alejandro Barone
  • 1,743
  • 2
  • 13
  • 24