无法将 Angular5 HttpClient 响应映射到我的打字稿 类
Can't map Angular5 HttpClient responses to my typescript classes
我在将我的 Angular 5 HttpClient 响应映射到具体的 TypeScript classes 时遇到问题。
我有一个关注 Angular 5 class:
export class MaintainableUser {
constructor(public id: string, public name: string, public privileges: string[]) {
}
public hasPrivilege(privilege: string): boolean {
return this.privileges.indexOf(privilege) != -1;
}
public togglePrivilege(privilege: string) {
if (this.hasPrivilege(privilege)) {
this.privileges.splice(this.privileges.indexOf(privilege), 1);
} else {
this.privileges.push(privilege);
}
console.log(this.privileges);
}
}
我有以下 Angular5 项服务:
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {MaintainableUser} from './maintain-users/maintainable-user';
import {Observable} from 'rxjs/Observable';
import {catchError} from 'rxjs/operators';
import {ApiErrorHandler} from '../api-error-handler';
@Injectable()
export class AdminService {
constructor(private http: HttpClient, private errors: ApiErrorHandler) {
}
getAllUsers(): Observable<MaintainableUser[]> {
return this.http.get<MaintainableUser[]>('api/admin/users').pipe(catchError(this.errors.handle));
}
}
这很好很干净,现在我可以像这样使用我的服务了:
import {Component, OnInit} from '@angular/core';
import {MaintainableUser} from './maintainable-user';
import {AdminService} from '../admin.service';
@Component({
selector: 'app-maintain-users',
templateUrl: './maintain-users.component.html',
styleUrls: ['./maintain-users.component.scss']
})
export class MaintainUsersComponent implements OnInit {
constructor(private adminService: AdminService) {
}
ngOnInit() {
this.reloadMaintainableUsers();
}
private reloadMaintainableUsers() {
this.adminService.getAllMaintainableUsers().subscribe(
data => {
console.log(data);
console.log(data[0] instanceof MaintainableUser);
data[0].hasPrivilege('ADMIN');
},
err => {
console.log('Service error: ' + err);
}
);
}
}
问题是我收到的数据实际上不是MaintainableUser的列表。来自我的 MaintainableUsersComponent 的响应块具有以下输出:
{"id": "john", "name": "John Doe", "privileges": ["ADMIN"]}
false
ERROR TypeError: _v.context.$implicit.hasPrivilege is not a function
这是为什么?为什么我的数据 [0] 不是 instanceof MaintainableUser?我是 Angular 的新手,但我从不同的教程中了解到,从第 4 版开始,我应该能够完全像那样自动映射到我的 classes/interfaces。或者它只是一个假的东西,所以你可以安全地确定你的对象是强类型的,但你不能确定它是实际对象本身的实例吗?如果我可以在我的响应 classes 中包含一些辅助方法,那将会非常好,这样我就可以在视图中使用它们,但目前我还没有找到一种干净的方法来做到这一点。
instanceof
检查原型链,因此除非您的 getAllMaintainableUsers()
正在创建新的 MaintainableUser
对象,否则它将 return 为假。我的猜测(根据您上面的 getAllUsers()
调用)是您直接 return 从服务中获取一个对象。即使您将类型注释为 MaintainableUser[]
,因为它不是使用 MaintainableUser
的原型创建的,instanceof 也不会 return 对于 data[0] instanceof MaintainableUser
.
为真
你的 MaintainableUser
type 映射得很好,所以 HttpResponse 正确地映射了泛型类型,Typescript 编译器没有抱怨,但你的回应是不是 MaintainableUser
的 实例 。它仍然只是一个从 JSON.
解析出来的对象
您的 MaintainableUser
class 有一个方法 属性,相当于将该方法添加到 MaintainableUser.prototype
。事实上,当针对 ES5 时,这正是 Typescript 编译器所做的。
请记住,Typescript 类型对转译的 Javascript 没有 影响。将 MaintainableUser[]
类型传递给 HttpClient
只是将强类型添加到响应中。本质上,您只是告诉您的 IDE 和编译器 Response 是 MaintainableUser[]
,但它实际上并不是 MaintainableUser
的 实例 。您需要使用 new
关键字来传递该原型。
我将重构 MaintainableUser
以接受该 Response 作为构造函数参数并将响应映射到 MaintainableUser
的新实例,或者将 hasPrivelage
方法移动到服务。
理解 classes/objects 的工作原理是相当困难的。从 API 返回的只是一个普通对象(已解析 JSON),它没有 MaintainableUser
的任何方法,因为它不是您的 class 的实例。它仅具有与您的 class.
相同的属性
您需要手动将值从对象传递到构造函数并创建 class 的实例。 Angular 不会自动执行。我经常这样做:
export class MaintainableUser {
public static createInstance({ id, name, privileges }): MaintainableUser {
return new MaintainableUser(id, name, privileges);
}
constructor(public id: string, public name: string, public privileges: string[]) {}
public hasPrivilege(privilege: string): boolean {
return this.privileges.indexOf(privilege) != -1;
}
public togglePrivilege(privilege: string) {
if (this.hasPrivilege(privilege)) {
this.privileges.splice(this.privileges.indexOf(privilege), 1);
} else {
this.privileges.push(privilege);
}
console.log(this.privileges);
}
}
然后:
getAllUsers(): Observable<MaintainableUser[]> {
return this.http.get<MaintainableUser[]>.('api/admin/users').pipe(
map(MaintainableUser.createInstance)
catchError(this.errors.handle)
);
}
我在将我的 Angular 5 HttpClient 响应映射到具体的 TypeScript classes 时遇到问题。
我有一个关注 Angular 5 class:
export class MaintainableUser {
constructor(public id: string, public name: string, public privileges: string[]) {
}
public hasPrivilege(privilege: string): boolean {
return this.privileges.indexOf(privilege) != -1;
}
public togglePrivilege(privilege: string) {
if (this.hasPrivilege(privilege)) {
this.privileges.splice(this.privileges.indexOf(privilege), 1);
} else {
this.privileges.push(privilege);
}
console.log(this.privileges);
}
}
我有以下 Angular5 项服务:
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {MaintainableUser} from './maintain-users/maintainable-user';
import {Observable} from 'rxjs/Observable';
import {catchError} from 'rxjs/operators';
import {ApiErrorHandler} from '../api-error-handler';
@Injectable()
export class AdminService {
constructor(private http: HttpClient, private errors: ApiErrorHandler) {
}
getAllUsers(): Observable<MaintainableUser[]> {
return this.http.get<MaintainableUser[]>('api/admin/users').pipe(catchError(this.errors.handle));
}
}
这很好很干净,现在我可以像这样使用我的服务了:
import {Component, OnInit} from '@angular/core';
import {MaintainableUser} from './maintainable-user';
import {AdminService} from '../admin.service';
@Component({
selector: 'app-maintain-users',
templateUrl: './maintain-users.component.html',
styleUrls: ['./maintain-users.component.scss']
})
export class MaintainUsersComponent implements OnInit {
constructor(private adminService: AdminService) {
}
ngOnInit() {
this.reloadMaintainableUsers();
}
private reloadMaintainableUsers() {
this.adminService.getAllMaintainableUsers().subscribe(
data => {
console.log(data);
console.log(data[0] instanceof MaintainableUser);
data[0].hasPrivilege('ADMIN');
},
err => {
console.log('Service error: ' + err);
}
);
}
}
问题是我收到的数据实际上不是MaintainableUser的列表。来自我的 MaintainableUsersComponent 的响应块具有以下输出:
{"id": "john", "name": "John Doe", "privileges": ["ADMIN"]}
false
ERROR TypeError: _v.context.$implicit.hasPrivilege is not a function
这是为什么?为什么我的数据 [0] 不是 instanceof MaintainableUser?我是 Angular 的新手,但我从不同的教程中了解到,从第 4 版开始,我应该能够完全像那样自动映射到我的 classes/interfaces。或者它只是一个假的东西,所以你可以安全地确定你的对象是强类型的,但你不能确定它是实际对象本身的实例吗?如果我可以在我的响应 classes 中包含一些辅助方法,那将会非常好,这样我就可以在视图中使用它们,但目前我还没有找到一种干净的方法来做到这一点。
instanceof
检查原型链,因此除非您的 getAllMaintainableUsers()
正在创建新的 MaintainableUser
对象,否则它将 return 为假。我的猜测(根据您上面的 getAllUsers()
调用)是您直接 return 从服务中获取一个对象。即使您将类型注释为 MaintainableUser[]
,因为它不是使用 MaintainableUser
的原型创建的,instanceof 也不会 return 对于 data[0] instanceof MaintainableUser
.
你的 MaintainableUser
type 映射得很好,所以 HttpResponse 正确地映射了泛型类型,Typescript 编译器没有抱怨,但你的回应是不是 MaintainableUser
的 实例 。它仍然只是一个从 JSON.
您的 MaintainableUser
class 有一个方法 属性,相当于将该方法添加到 MaintainableUser.prototype
。事实上,当针对 ES5 时,这正是 Typescript 编译器所做的。
请记住,Typescript 类型对转译的 Javascript 没有 影响。将 MaintainableUser[]
类型传递给 HttpClient
只是将强类型添加到响应中。本质上,您只是告诉您的 IDE 和编译器 Response 是 MaintainableUser[]
,但它实际上并不是 MaintainableUser
的 实例 。您需要使用 new
关键字来传递该原型。
我将重构 MaintainableUser
以接受该 Response 作为构造函数参数并将响应映射到 MaintainableUser
的新实例,或者将 hasPrivelage
方法移动到服务。
理解 classes/objects 的工作原理是相当困难的。从 API 返回的只是一个普通对象(已解析 JSON),它没有 MaintainableUser
的任何方法,因为它不是您的 class 的实例。它仅具有与您的 class.
您需要手动将值从对象传递到构造函数并创建 class 的实例。 Angular 不会自动执行。我经常这样做:
export class MaintainableUser {
public static createInstance({ id, name, privileges }): MaintainableUser {
return new MaintainableUser(id, name, privileges);
}
constructor(public id: string, public name: string, public privileges: string[]) {}
public hasPrivilege(privilege: string): boolean {
return this.privileges.indexOf(privilege) != -1;
}
public togglePrivilege(privilege: string) {
if (this.hasPrivilege(privilege)) {
this.privileges.splice(this.privileges.indexOf(privilege), 1);
} else {
this.privileges.push(privilege);
}
console.log(this.privileges);
}
}
然后:
getAllUsers(): Observable<MaintainableUser[]> {
return this.http.get<MaintainableUser[]>.('api/admin/users').pipe(
map(MaintainableUser.createInstance)
catchError(this.errors.handle)
);
}