0

I've tried all the other solutions posted on stack in reference to error TS2322 but haven't been able to find a solution that works.

Error produced

ERROR in src/app/service/user.service.ts(21,9): error TS2322: Type 'Observable<{} | User>' is not assignable to type 'Observable<User>'.
  Type '{} | User' is not assignable to type 'User'.
    Type '{}' is not assignable to type 'User'.
      Property 'id' is missing in type '{}'.

user.service

import { Injectable } from '@angular/core';
import { BaseService } from './base.service';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment';
import { User } from '../model/user';
import { MessageService } from './message.service';
import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';

@Injectable({
    providedIn: 'root'
})
export class UserService extends BaseService {

    constructor(
        http: HttpClient,
        messageService: MessageService,
    ) { super(messageService, http); }

    login(login: string, password: string): Observable<User> {
        // Error thrown on line below
        return this.http.post<User>(environment.serverUrl + 'api/user/login', {'login': login, 'password': password}).pipe(
            tap(user => this.log(`logged in ` + user)),
            catchError(this.handleError('login'))
        );
    }
}

user.ts

import { BlogPost } from "./blog-post";
import { JobNote } from "./job-note";
import { BaseModel } from "./base-model";

export class User extends BaseModel {
    id: number;
    login: string;
    name: string;
    api_token: string;
    isAdmin: boolean;
    email: string;
    address1: string;
    address2: string;
    address3: string;
    phoneHome: string;
    phoneWork: string;
    phoneMobile: string;
    fax: string;
    blogPosts: BlogPost[];
    notes: JobNote[];
}

base.service

import { Injectable } from '@angular/core';
import { User } from '../model/user';
import { ApprovedClaim } from '../model/approved-claim';
import { BlogCategory } from '../model/blog-category';
import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { MessageService } from './message.service';
import { throwError } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { environment } from '../../environments/environment';

export class BaseService {
    constructor(
        protected messageService: MessageService,
        protected http: HttpClient,
    ) { }

    protected handleError<T>(operation = 'operation', result?: T) {
        return (error: any): Observable<T> => {
            let errMsg = `error in ${operation}()`;
            console.error(error); // log to console instead

            this.log(`${operation} failed: ${error.message}`);

            return throwError(errMsg);
        };
    }

    protected log(message: string) {
        this.messageService.add(message);
    }
}

Changing from User to any

Someone had suggested (deleted answer) changing Observable<User> to Observable<any>, this compiles but why? what's the difference between having it expect a User object as response.

Edit: In reference to the duplicate tag, I'm already doing the suggested answers. The error message is also about The observable User object not matching users, instead of an empty object.

Bankzilla
  • 2,086
  • 3
  • 25
  • 52
  • 1
    Possible duplicate of [Observable<{}> not assignable to type Observable](https://stackoverflow.com/questions/37221062/observable-not-assignable-to-type-observablesometype) – alt255 Aug 02 '18 at 18:21
  • 1
    What does `this.handleError` look like? My guess is that the return of that introduces the `{}` since there is a branch (the error one) where you will not return a user. I can't test right now though. – Titian Cernicova-Dragomir Aug 02 '18 at 18:39
  • @TitianCernicova-Dragomir updated to include `base.service` which has the handleError method. – Bankzilla Aug 02 '18 at 18:43

1 Answers1

1

The handleError function has a generic parameter, if you don't specify it, the function will return (error: any) => Observable<{} > introducing the {} in the final result.

Try this :

login(login: string, password: string): Observable<User> {
    return this.http.post<User>(environment.serverUrl + 'api/user/login', {'login': login, 'password': password}).pipe(
        tap(user => this.log(`logged in ` + user)),
        catchError(this.handleError<User>('login'))
    );
}
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357