Angular 服务 - 返回的对象类型是对象,而不是指定的泛型类型
Angular Service - Type of object returned is object and not that of the generic type specified
我有一个 angular5 服务,它执行 HTTP 获取和 returns 如下所示的特定类型
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)
);
}
产品 class 是具有属性和方法的 class。下面是一小段摘录。
class Product{
productID:string;
productName:string;
setQuantity(quantity:number){
}
}
当我在 get 返回的 this._product 上调用 setQuantity 函数时,出现 'setQuantity is not a function' 错误。当我尝试检查 this._product 的实例时,它不是 Product 类型,而是 Object 类型。
在get方法上设置泛型类型只是为了帮助编译时类型检查吗?如何从 getProductByIDproductId 方法获取产品 class 的具体实例?
例如,您可以映射响应。
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 对象。
EDIT 你可以创建一个对象 "by hand" 只有几行:
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))
据我所知,要指定响应类型,您应该使用接口 类,因此您的产品应该是一个接口:
interface Product{
productID:string;
productName:string;
}
因为它只是接口和 http 响应,所以它不应该有任何方法
编辑
@trichetriche 的回答可能是这个问题的解决方案之一。
你不能做你正在做的事。
当您从 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
class 中未定义的属性,您也可以 运行 遇到性能问题。
我有一个 angular5 服务,它执行 HTTP 获取和 returns 如下所示的特定类型
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)
);
}
产品 class 是具有属性和方法的 class。下面是一小段摘录。
class Product{
productID:string;
productName:string;
setQuantity(quantity:number){
}
}
当我在 get 返回的 this._product 上调用 setQuantity 函数时,出现 'setQuantity is not a function' 错误。当我尝试检查 this._product 的实例时,它不是 Product 类型,而是 Object 类型。
在get方法上设置泛型类型只是为了帮助编译时类型检查吗?如何从 getProductByIDproductId 方法获取产品 class 的具体实例?
例如,您可以映射响应。
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 对象。
EDIT 你可以创建一个对象 "by hand" 只有几行:
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))
据我所知,要指定响应类型,您应该使用接口 类,因此您的产品应该是一个接口:
interface Product{
productID:string;
productName:string;
}
因为它只是接口和 http 响应,所以它不应该有任何方法
编辑
@trichetriche 的回答可能是这个问题的解决方案之一。
你不能做你正在做的事。
当您从 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
class 中未定义的属性,您也可以 运行 遇到性能问题。