Reputation: 31
I have a rather complex code have been on for two days, I am using the map operator from rxjs operator to bring the values of IUser
from the IUser
interface. But I keep getting this error:
Argument of type 'OperatorFunction<IUser, void>' is not assignable to parameter of type 'OperatorFunction<Object, void>'. The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? Type 'Object' is missing the following properties from type 'IUser': email, displayName, token.
Thanks in advance.
Account.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { map } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { IUser } from '../shared/models/user';
@Injectable({
providedIn: 'root'
})
export class AccountService {
baseUrl = environment.apiUrl;
private currentUserSource = new BehaviorSubject<IUser>(null!);
currentUser$ = this.currentUserSource.asObservable();
constructor(private http: HttpClient, private router: Router) { }
login(values: any) {
return this.http.post(this.baseUrl + 'account/login', values).pipe(
map((user: IUser) => {
if (user) {
localStorage.setItem('token', user.token);
this.currentUserSource.next(user)
}
})
);
}
login.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
User.ts
export interface IUser {
email: string;
displayName: string;
token: string;
}
Upvotes: 1
Views: 1134
Reputation: 51350
From HttpClient
post()
,
Overload #14
post(url: string, body: any | null, options?: {
headers?: HttpHeaders | {
[header: string]: string | string[];
};
context?: HttpContext;
observe?: 'body';
params?: HttpParams | {
[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
};
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}): Observable<Object>;
Without specify T
for .post()
[Overload #14], it will return Observable<Object>
value.
Overload #15
post<T>(url: string, body: any | null, options?: {
headers?: HttpHeaders | {
[header: string]: string | string[];
};
context?: HttpContext;
observe?: 'body';
params?: HttpParams | {
[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
};
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}): Observable<T>;
From post()
[Overload #15], you have to specify T
for example post<T>()
, so that it will return Observable<T>
value.
Assumption: The response returned is IUser
type.
Specify T
as IUser
or any
type to solve the error mentioned.
As @Gunnar's comment, you have to use tap
instead of map
to perform the operation from the source observable without altering it.
Using map
must return a value for Observable
.
login(values: any) {
return this.http.post<IUser>(this.baseUrl + 'account/login', values).pipe(
tap((user: IUser) => {
if (user) {
localStorage.setItem('token', user.token);
this.currentUserSource.next(user);
}
})
);
}
Upvotes: 1