【问题标题】:Angular 6 and typed API dataAngular 6 和类型化 API 数据
【发布时间】:2018-09-24 13:19:38
【问题描述】:

我对 Angulartypescript 非常陌生,并且一直在阅读一些关于返回类型化数据的帖子。有些文章声明您必须在从服务返回对象后映射您的对象,其他文章只需在调用中键入结果。 Angular 6 中获取强类型数据的最简单方法是什么?以下不起作用我真的需要手动映射每个属性吗?

我的模特:

export interface MenuItem {
    menuItemsId:number;
    groupCode: number;
    groupDescription: string;
    subGroupCode:number;
    subGroupDescription:string;
    itemCode:number;
    itemDescription:string;
    grade:string;
    remark:string;
}

我的服务:

getValues():Observable<MenuItem[]>{
return  this.httpClient.get<MenuItem[]>("https://hafnia-asset-control-dev.azurewebsites.net/api/menuitems/cosmetic");  
}

呼叫:

var t = this.apiService.getValues().subscribe((data) => {
  this.menuItems  =  data;
  console.log(this.menuItems);

});

JSON 结果:

[{"menuItemsId":1,"groupCode":1000,"groupDescription":"xxx","subGroupCode":1000,"subGroupDescription":"SHELL","itemCode":1001,"itemDescription":"ccc","grade":"Int","remark":"String"},{"menuItemsId":2,"groupCode":1000,"groupDescription":"COSMETIC","subGroupCode":1000,"subGroupDescription":"xxx","itemCode":1002,"itemDescription":"xxx","grade":"Int","remark":"String"}

app.module:

providers: [AdalService, AdalGuard,{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }],

拦截器:

import { Injectable } from '@angular/core';
import { HttpEvent,HttpHandler,HttpRequest,HttpInterceptor } from '@angular/common/http';
import { AdalService } from 'adal-angular4';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    constructor(private adalService: AdalService) { }

    intercept(req: HttpRequest<any>, next:HttpHandler): Observable<HttpEvent<any>>{
        const authHeader = this.adalService.userInfo.token;

        const authReq = req.clone({headers: req.headers.set('Authorization', `Bearer ${authHeader}`)});
        return next.handle(authReq);
    }

}

【问题讨论】:

  • 如果你的API数据具有相同的属性,你不需要一一映射,它应该可以工作。但请注意,您定义的构造函数不会被调用,因为键入服务调用更方便和清晰
  • 你应该使用get&lt;MenuItem[]&gt;而不是get&lt;Array&lt;MenuItem&gt;&gt;,并且只有当该URL返回一个与MenuItem匹配的数组时它才会起作用,否则你会看起来没有数据
  • @mast3rd3mon - you should use get&lt;MenuItem[]&gt; not get&lt;Array&lt;MenuItem&gt;&gt; Array<Type> VS Type[] in Typescript
  • 谢谢大家。我更新了代码是有道理的。但是我仍然得到一个对象列表。见主帖中的图片。
  • 谢谢@mast3rd3mon 我试过你的建议,但还是一样:( typeof data[0] "object"

标签: angular


【解决方案1】:

你读到的所有文章都是正确的。

当您执行this.httpClient.get&lt;YourType&gt; 之类的操作时,这称为类型断言。这意味着您会将生成的对象视为 YourType,它将在您的 IDE 中启用自动完成功能,在调用未定义属性时在编译时抛出错误等......但该对象不会是 YourType 的真实实例在运行时。

如果YourType 只包含属性,那么就像您将它用作interface,所以没关系:您只是防止自己误用您的对象。另一方面,当转译为 Javascript 时,类型将永远不会显示,您的对象将显示为文字对象。

如果YourType 包含您要在实例化对象上调用的非静态函数、getter、setter,那么您必须添加一个映射this.httpClient.get&lt;YourType&gt;("url").pipe(map(x =&gt; new YourType(x)) 和一个构造函数:

class YourType {
   // Properties...
   constructor(obj: any) {
      Object.assign(this, obj);
   }
}

这样你会得到YourType的真实实例

【讨论】:

  • 想知道它是否与我有一个自定义拦截器有关?我把它添加到主帖中。
  • 我也没有得到反对意见。但是刚刚投了赞成票。
  • @ThomasSegato 既然你想要一个Array,你必须将它映射为Array,你做到了吗? this.httpClient.get&lt;MenuItem[]&gt;("url").pipe(map(x =&gt; x.map(y =&gt; new MenuItem(y))))
  • 我刚刚在这个线程中被告知使用界面时不需要?只有当它是一个类?
  • 很抱歉,我没有得到您的期望。在评估typeof data[0] 时,我假设您仍然拥有"object"。如果这是您的问题,而您希望看到 "MenuItem",那么您必须使用构造函数进行映射,因为如果您不这样做,则该类型根本不会反映在 Javascript 生成的代码中。
猜你喜欢
  • 2019-07-11
  • 1970-01-01
  • 2019-03-22
  • 2019-02-08
  • 2019-02-08
  • 1970-01-01
  • 2018-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多