solange
solange

Reputation: 103

Type 'null' is not assignable to type 'string'. Angular/TypeScript

I have an error message:

Type 'null' is not assignable to type 'string'.

enter image description here

I found a solution here but I didn't understand the answers for my problem.

My code is presented like this:

const expectedRole = route.data['expectedRole'];
const token = localStorage.getItem('token');
    
const { userName, roleId } = decode(token);
console.log(roleId);

enter image description here

Edit 2022-02-02

enter image description here

decode method

export class InvalidTokenError extends Error {}

export interface JwtDecodeOptions {
  header?: boolean;
}

export interface JwtHeader {
  type?: string;
  alg?: string;
}

export interface JwtPayload {
  iss?: string;
  sub?: string;
  aud?: string[] | string;
  exp?: number;
  nbf?: number;
  iat?: number;
  jti?: string;
}

export default function jwtDecode<T = unknown>(
  token: string,
  options?: JwtDecodeOptions
): T;

FYI, I copied the code from the project here

Upvotes: 1

Views: 22495

Answers (3)

brayan141
brayan141

Reputation: 21

I was able to fix the problem by modifying this:

export class RoleGuard implements CanActivate {

  constructor(
    private authService: AuthService,
    public router: Router
  ){ }
  canActivate(route: ActivatedRouteSnapshot):boolean{
    const expectedRole = route.data.expectedRole;
    const token = localStorage.getItem('token');

const { userName, roleId } = decode(token);
console.log(roleId);

if( !this.authService.isAuth() || roleId !== expectedRole){
  console.log('Usuario no autorizado para la vista');
  this.router.navigate(['login']);
  return false;
}
return true;
  }  
}

To this:

export class RoleGuard implements CanActivate {

  constructor(
    private authService: AuthService,
    public router: Router
  ) { }
  canActivate(route: ActivatedRouteSnapshot): boolean {
    const expectedRole = route.data['expectedRole'];
    const token = localStorage.getItem('token');

    if (!this.authService.isAuth()) {

      console.log('Usuario no autorizado para la vista');
      this.router.navigate(['login']);
    };
    const info: { userName: string, roleId: string } = decode(token);
    if (info.roleId != expectedRole) {
      console.log('Usuario no autorizado para la vista');
      this.router.navigate(['login']);

      return false;
    }
    return true;
  }
}

I separated the if into two ifs, each one performing an independent activity.

Upvotes: 2

Chris Hamilton
Chris Hamilton

Reputation: 10946

This is just the typescript compiler telling you that token may be null. So you need to check that it isn't before using it in the decode function, since decode does not accept a null parameter.

const expectedRole = route.data['expectedRole'];
const token = localStorage.getItem('token');

if (token) const { userName, roleId } = decode(token);
console.log(roleId);

You can also force the typescript compiler to ignore this using !, which says "this variable will be truthy, trust me", but you need to be absolutely sure it will never be null, or you may get a runtime error.

const expectedRole = route.data['expectedRole'];
const token = localStorage.getItem('token');
    
const { userName, roleId } = decode(token!);
console.log(roleId);

Edit

This solution should work regardless, but you should define the correct return types for decode

const expectedRole = route.data['expectedRole'];
const token = localStorage.getItem('token');

if (token) const info: { userName, roleId } = decode(token);
console.log(info.roleId);

OR

const expectedRole = route.data['expectedRole'];
const token = localStorage.getItem('token');

if (token) const info: any = decode(token);
console.log(info.roleId);

Edit 2

Looks like decode is a generic function, so you can define the return type like this:

const expectedRole = route.data['expectedRole'];
const token = localStorage.getItem('token');

if (token) const { userName, roleId } = decode<{ userName, roleId }>(token);
console.log(roleId);

Upvotes: 3

Gianfabio Pezzolla
Gianfabio Pezzolla

Reputation: 389

Thinking like typescript thinks, you need to define a type (i.e. "string", "number", "void") for variables as well as functions or methods.

Ones you have defined type for variables (or for methods), typescript check if its type match with its definition.

In your case token is probably null and typescript alert you that string not match with null and rise an error.

So you need to debug token and check if:

  • is not null nor undefined
  • is a string

In some cases you need to declare type of variable in the following way:

token: string = ...

Upvotes: 0

Related Questions