0

I've created this service to handle auth and it is working fine...

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { tap } from 'rxjs/operators';
import { Storage } from '@ionic/storage';
import { EnvService } from './env.service';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

export class AuthService {

  isLoggedIn = false;
  token:any;

  constructor(
    private storage:Storage,
    private http: HttpClient,
    private env: EnvService,
  ) { }

  login(email: String, password: String) {

    let formData = {
      usuario    : email,
      senha      : password,
      retsession : true
    }

    return this.http.post(this.env.API_URL+'/login', formData).pipe(
      tap(response => {
        var token = ('jwt' in response) ? response.jwt : null ;
        this.storage.set('token', token)
        .then(
          () => { console.log('Token Stored: ' + token); },
          error => console.error('Error storing item', error)
        );
        this.token = token;
        this.isLoggedIn = true;
        return token;
      }),
    );
  }

}

Even it is working, I'm getting a compile error

[ng] ERROR in src/app/services/auth.service.ts(36,52): error TS2339: Property 'jwt' does not exist on type 'never'.

This error is on the line when I check if my token is present in http response data...

What is the correct way to check this avoiding this error?

anderlaini
  • 1,593
  • 2
  • 24
  • 39

2 Answers2

3

To check if the token is present you could do:

let token = response['jwt'] ? response['jwt'] : null ;

Kind regards

sagat
  • 1,351
  • 12
  • 15
2

sagat's answer is correct. Here is an example of how to pass an interface into an http call:

// form-data.interface.ts
export interface FormData {
  usuario: string;
  senha: string;
  retsession: boolean;
}

// login-response.interface.ts
export interface LoginResponse {
  jwt: string;
  // other properties
}

// login.service.ts
login(formData: FormData): Obvservable<LoginResponse> {
  return this.http.post<LoginResponse>(`${this.env.API_URL}/login`, formData);
}

// call this from your component (login.component.ts) or your state management (login.state.ts)
// call it like so
this.login(formData).subscribe((response) => {
  // perform your logic with the response
}

Your http post will return an observable that you can subscribe to. Pipe and tap are not needed here but basically do the same thing.

Note: Instead of an interface if you're not receiving values for properties you're expecting you can use a class like so:

// login.response.model.ts
export class LoginResponse {
  jwt: string
  // other properties

  constructor(data: LoginResponse) {
    this.jwt = (data && data.jwt) ? data.jwt : '';
  }
}

This method will make sure all properties exist on the model and are set and have initial values. You won't encounter any errors if pieces of data are missing.

Mickers
  • 1,367
  • 1
  • 20
  • 28
  • 1
    could you please edit your answer describing file names for each block of code? afaik the login method should be placed in service and it should be called from a controller with subscribe... right? – anderlaini Aug 02 '19 at 18:31