Anand Vaidya
Anand Vaidya

Reputation: 649

Getting error in Angular: Type 'boolean | Observable<boolean>' is not assignable to type 'boolean'

Checkout this answer to understand the approach. I am using to the same solution to implement the master guard as I have multiple guards and want to execute them in sequence.

In Master Guard -

return guard.canActivate(this.route, this.state);

The whole function is Specified below:

//Create an instance of the guard and fire canActivate method returning a promise
    private activateGuard(guardKey: string): Promise<boolean> {

        let guard: Guard1 | Guard2 | Guard3 | Guard4;

        switch (guardKey) {
            case GUARDS.GUARD1:
                guard = new Guard1();
                break;
            case GUARDS.GUARD2:
                guard = new Guard2();
                break;
            case GUARDS.GUARD3:
                guard = new Guard3();
                break;
            case GUARDS.GUARD4:
                guard = new Guard4(this._Guard4DependencyService);
                break;
            default:
                break;
        }
        return guard.canActivate(this.route, this.state);
    }

I am getting the error mentioned below:

Type 'boolean | Observable<boolean>' is not assignable to type 'boolean'.
  Type 'Observable<boolean>' is not assignable to type 'boolean'.

Please find stackblitz link for the same

Screenshot shared below: I am getting this error as shown in screenshot Please share your solution to get rid of this error. Any help is appreciated thanks in advance!

Upvotes: 0

Views: 3240

Answers (2)

Siddhant
Siddhant

Reputation: 3171

As per the stackblitz code shared, the guard is defined as:

    let guard: Guard1 | Guard2;

So guard can be either of the type Guard1 or Guard2, and each of those classes have a different canActivate method return type. One has return type Observable<boolean>, while another has Promise<boolean> .

The return guard.canActivate(this.route, this.state); statement can either return Observable<boolean> or Promise<boolean>, whereas the function containing the return statement is defined to return Promise<boolean>.

Do you really need canActivate method of Guard1 and Guard2 class to have different return types? If you can keep the return type consistent, then that should resolve the issue.

In case if your requirement is still to have different return types, then in case when guard is assigned to Guard2 instance, the return statement should be as:

    return guard.canActivate(this.route, this.state).toPromise();

Upvotes: 1

Devang Patel
Devang Patel

Reputation: 1843

I see your issue now. guard1 service and guard2 service are having two different return types. You need to have both return type as Promise<boolean> as per MasterGuard service code.

If you see activateGuard() in MasterGuard service then it is expecting for Promise<boolean>. However, in guard1 service, you have returned Observable<boolean>.

guard1.service.ts :

@Injectable()
export class Guard1 implements CanActivate, CanActivateChild {
  
  constructor(private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
    console.log('Chain-1');
    return Promise.resolve(true)   // Modified this part
  }

  canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
    return this.canActivate(route, state);
  }
}

guard2.service.ts :

@Injectable()
export class Guard2 implements CanActivate, CanActivateChild {
  
  constructor() {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
    console.log('Chain-2');
    return Promise.resolve(true);
  }

  canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
    return this.canActivate(route, state);
  }
}

Working code: https://stackblitz.com/edit/angular-route-guards-9tzxmv

Issue was because of this line:

switch (guardKey) {
  case GUARDS.GUARD1:
    guard = new Guard1(this._Router);   // because of this line it was creating issue
    break;
  case GUARDS.GUARD2:
    guard = new Guard2();
    break;
  default:
    break;
}

Upvotes: 1

Related Questions