0

I am working on a project using ASP.NET Core Web API and Angular 13.

The login post request from the endpoint is:

> https://localhost:44396/api/v1/auth/login

    {
       "status_code": 200,
       "message": "Successfully Logged In",
       "result": {
           "token": "gggggffffffffffffdddddddddddd",
           "user": {
               "id": 3,
               "user_name": "smith",
               "last_login": "2022-01-03T12:35:26.0305649"
              },
           "roles": [
               "Teacher"
           ],
           "expires": "2022-01-03T14:40:33Z"
       }
    }

This is the Angular code:

user.ts:

export interface IResponse<T> {
  message: string;
  error: boolean;
  code: number;
  results: T;
}

export interface IUser {
  userName?: string;
  lastLogin?: Date;
  token?: string;
  roles?: string[];
  expires?: Date;
}

auth.service.ts:

export class AuthService {
  baseUrl = environment.apiUrl;
  private currentUserSource = new ReplaySubject<IUser>(1);
  currentUser$ = this.currentUserSource.asObservable();

  constructor(private http: HttpClient, private router: Router) { }

  login(model: any){
    return this.http.post(this.baseUrl+'auth/login', model).pipe(
      map((res: IUser)=>{
        const user = res;
        if(user){
          this.setCurrentUser(user);
        }
      })
    )
  }

  setCurrentUser(user: IUser){
    if(user){
      user.roles = [];
      const roles = this.getDecodedToken(user.token).role;//copy token to jwt.io see .role
      Array.isArray(roles) ? user.roles = roles : user.roles.push(roles);
      localStorage.setItem('user', JSON.stringify(user));
      this.currentUserSource.next(user);
    }
  }

  getDecodedToken(token: string) {
    return JSON.parse(atob(token.split('.')[1]));
  }
}

I got this error:

error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.

With this code highlighted in setCurrentUser: user.token

How do I resolve it?

3
  • 1
    What did you expect to happen? Per the definition of IUser, token?: string - it's optional, a given user might not have a token property. But the getDecodedToken function defines its parameter as token: string - that must be a string. Somewhere you need to deal with the fact that those don't add up - we can't tell you exactly how, you need to decide if those types are correct and, if so, what should happen if user.token is undefined. Commented Jan 3, 2022 at 17:15
  • @jonrsharpe - After login, I want to store toekn user_name, last_login, roles into the local storage Commented Jan 3, 2022 at 17:22
  • And again, what should happen if the user.token is undefined, as the types you've defined allow it to be, when you come to pass it to getDecodedToken. Also you seem to be dealing with a token like a JWT but not actually validating it - what did you think the other parts separated by . were for? Commented Jan 3, 2022 at 17:25

3 Answers 3

2

Please try

const roles = this.getDecodedToken(user.token || '').role;
Sign up to request clarification or add additional context in comments.

1 Comment

And what do you think getDecodedToken does with an empty string? This passes type checking, but is otherwise completely wrong.
1

try to change the "if (user) { " in your code by this:

if (user && user.token) {

It should be enough to TypeScript to know that user.token actually exists, despite the fact that your interface says that it is optional.

If it doesn't work, try this variation:

if (user && user.token != null) {

Comments

0

You can change the interface:

export interface IUser {
  ...
  token: string;
}

If you're certain you'll always get a token, as long as you get a user.

Alternatively, you can explicitly assert string type:

// Change this:
this.getDecodedToken(user.token)
// to this:
this.getDecodedToken(user.token as string)

And best to do is to make sure you have one, like the other answer suggests:

if (user && user.token) {...}

2 Comments

user.token as string does not cast it, it's just a type assertion (and if the original type is correct, one that's potentially a lie).
Correct, thanks, edited the post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.