Angular Service - 返回的对象类型是object而不是指定的泛型类型

时间:2018-03-16 10:53:53

标签: angular typescript angular5 rxjs5

我有一个angular5服务,它执行HTTP get并返回一个特定类型,如下所示

public getProductByIDproductId: string): Observable<Product> {
    const headers = new HttpHeaders({ "Content-Type": "application/json" });
    const url = `${environment.productservice_baseurl}/${productId}`;
    return this.http
      .get<Product>(url, { headers: headers })
      .pipe(       
        tap(data => (this._product = data)),
        catchError(this.handleError)
      );
  }

Product类是一个具有属性和方法的类。下面有一小段摘录。

class Product{
    productID:string;
    productName:string;

    setQuantity(quantity:number){

    }
}

当我在get.uproduct上调用setQuantity函数时,得到'setQuantity不是函数'错误。当我尝试检查this._product的实例时,它不是Product类型,而是类型Object。

get方法上设置的泛型类型是否仅用于帮助编译时类型检查?如何从getProductByIDproductId方法获取产品类的具体实例?

3 个答案:

答案 0 :(得分:5)

你无法做你正在做的事情。

当您从URL获取数据时,您只获得JSON。您告诉TypeScript data类型为Product,但这只是编译器的提示而不是真的。

data未通过调用new Product创建,因此它不会共享其方法。

如果您希望this._product的行为与原生Product实例相同,则可以执行以下操作:

this._product = data;
Object.setPrototypeOf(this._product, Product.prototype);

这样您就可以将this._product转换为真实的Product实例,包括其方法。

另一种选择,如果您担心setPrototypeOf及其潜在的性能缺陷,就是这样做:

this._product = new Product();
Object.assign(this._product, data);

当然,如果Product具有无参数构造函数,这只是一个好主意。而且,无论如何,如果data具有未在Product类中定义的属性,您也可能会遇到性能问题。

答案 1 :(得分:2)

您可以映射响应。

return this.http
  .get<Product>(url, { headers: headers })
  .map(response => new Product(response)) // I don't know your constructor
  .pipe(       
    tap(data => (this._product = data)),
    catchError(this.handleError)
  );

这样,您确定您的对象将是您定义的Typescript对象。

编辑您可以手动创建对象&#34;&#34;只有几行:

export class Product {
  // Your class ...

  public static createProductFromHttpResponse = (response: any) => {
    const ret = new Product();
    for (let key in response.key) { ret[key] = response[key]; }
    return ret;
  }
}

在您的地图中:

  .map(response => Product.createProductFromHttpResponse(response))

答案 2 :(得分:0)

据我所知,要指定响应类型,您应该使用接口而不是类,因此您的产品应该是一个接口:

interface Product{
productID:string;
productName:string;

}

因为它只是接口和http响应,所以它不应该有任何方法

修改

@trichetriche的回答可能就是这个问题的解决方案之一。