7

When someone registers, I post the info to my back-end. When successfully registering a user, I get a json response back of {success: true, msg: "User registered"}. My problem is when I try to do an if statement to check if success is set to true.

Here is my code that isn't working:

    // Register User
    this.apiService.registerUser(user).subscribe(data => {
      if(data.success) {
        this.flashMessage.show('Registration successful', { cssClass: 'alert-success', timeout: 3200 });
      } else {
        this.flashMessage.show('Registration failed', { cssClass: 'alert-danger', timeout: 3200 });
      }
    });

I was able to console.log the response of data, and it returned:

{success: true, msg: "User registered"}

Here is the code from my ApiService:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

import { User } from '../models/User';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  private baseUri: string = 'http://localhost:5000/api';
  private headers = new HttpHeaders().set('Content-Type', 'application/json');

  constructor(private http: HttpClient) { }

  registerUser(user: User) {
    return this.http.post(this.baseUri + '/register', user, { headers: this.headers });
  }
}

Here is the code from my Register Component:

onRegisterSubmit() {
    const user: User = {
      firstName: this.firstName,
      lastName: this.lastName,
      email: this.email,
      username: this.username,
      password: this.password
    };

// Register User
    this.apiService.registerUser(user).subscribe(data => {
      console.log(data);
    });

  }

Screenshot of error from ng serve

I'm quite new to working with angular let alone a back-end, so if you could explain why this error was occurring it would be greatly appreciated.

Please let me know if you need any more information.

Jonathan
  • 2,700
  • 4
  • 23
  • 41
Brian
  • 85
  • 1
  • 2
  • 8
  • 1
    can you post the actual error stack? does it happen at runtime, or compile time? – muradm Dec 17 '18 at 22:47
  • is `success` a result of what's being returned from the `POST`, or are you trying to access something on the `HttpResponse` itself? – joh04667 Dec 17 '18 at 22:52
  • `success` is a result of what's being returned from the `POST`. Here is a screenshot of the console error https://i.stack.imgur.com/9rCBR.png – Brian Dec 17 '18 at 22:58
  • Possible duplicate of [error TS2339: Property 'x' does not exist on type 'Y'](https://stackoverflow.com/questions/38324949/error-ts2339-property-x-does-not-exist-on-type-y) – muradm Dec 17 '18 at 23:17
  • 3
    I overcome this issue by Identifying the type of `res` as `any`. So it should be like this: `this.http.post('http://localhost:3000/api', obj).subscribe((res:any) => { console.log(res.success) }` – TMA Jan 10 '20 at 06:47

3 Answers3

7

This is a compiler error, and it's one of the reasons Typescript is awesome!

Your registerUser method's return type is implicitly an Object (or {}) because that's what http.post is returning. http.post accepts a generic parameter to define what will be coming back in the response's body. Without that parameter, it will return type {} (because, without some sort of definition, JSON is just an unknown Object)... and a key of success does not exist on {}.

Assuming you have a fleshed out response object, just strongly type it:

interface UserPostResponse {
  success: boolean
}

...

  registerUser(user: User): Observable<UserPostResponse> {
    return this.http.post<UserPostResponse>(this.baseUri + '/register', user, { headers: this.headers });
  }

Conversely, if you wanted the HttpRequest itself and not the body, you just have to tell the HttpClient what part of the response to observe:

  registerUser(user: User): Observable<HttpResponse<object>> {
    return this.http.post(this.baseUri + '/register', user, { headers: this.headers }, observe: 'response');
  }

...and HttpResponse has a status, statusText, body, etc.

joh04667
  • 7,159
  • 27
  • 34
  • Wa about to post the same thing about HttpClient.post generics https://stackblitz.com/edit/angular-http-client-post-generics?file=src/app/app.component.ts – Wilhelmina Lohan Dec 17 '18 at 23:02
  • 1
    Thank you so, so, so much. I have been trying to find my way around this for close to 2 weeks now haha. Thank you too @WilliamLohan for the stackblitz. – Brian Dec 17 '18 at 23:16
4

Property 'success' does not exist on type 'Object'. Create code as:

// Register User
this.apiService.registerUser(user).subscribe( (data) => {
    if(data['success']) {
        this.flashMessage.show('Registration successful', { cssClass: 'alert-success', timeout: 3200 });
    } else {
        this.flashMessage.show('Registration failed', { cssClass: 'alert-danger', timeout: 3200 });
    }
});

This change correct my error in Angular ts file.

סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
Mishan Madhupa
  • 421
  • 4
  • 5
1

error TS2339: Property 'x' does not exist on type 'Y'

Is compile time error. Angular HttpClient has various post function declarations, one of which is:

post<T>(url: string, body: any | null, options?: { ... }): Observable<T>;

Where you can strongly type your type of response. You can introduce response interface and use it like:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

import { Observable } from 'rxjs';

import { User } from '../models/User';

export interface RegisterResponse {
  success: boolean;
  msg: string;
}

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  private baseUri: string = 'http://localhost:5000/api';
  private headers = new HttpHeaders().set('Content-Type', 'application/json');

  constructor(private http: HttpClient) { }

  registerUser(user: User): Observable<RegisterResponse> {
    return this.http.post<RegisterResponse>(this.baseUri + '/register', user, { headers: this.headers });
  }
}

Then you will be type safe from TypeScript compiler perspective.

Otherwise, matched declaration will be:

post(url: string, body: any | null, options?: { ... }): Observable<Object>;

Where Object has no declared property succuess, thus will cause that error.

Another way to avoid it is to use as any or any, see references below. But normally, you would want TypeScript to track your types.

TypeScript is strongly typed, meaning that it will attempt to make sure that data types your are using are actually correct. So if you are trying to refer to some property which has no known type, it will complain.

You may see also:

And so on to understand the matter.

muradm
  • 1,973
  • 19
  • 30
  • Wa about to post the same thing about HttpClient.post generics https://stackblitz.com/edit/angular-http-client-post-generics?file=src/app/app.component.ts – Wilhelmina Lohan Dec 17 '18 at 23:02