typescript 通过映射将类型(接口)转换为 observable
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49627239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Casting a type (interface) via map to observable
提问by Timothy
I've been learning TypeScript with Angular. And currently I stuck as this moment. Previously I used subscribed method and everything works flawlessly, but not I decided to rewrite the code using async pipe and it just does't work....
我一直在用 Angular 学习 TypeScript。而目前我停留在这一刻。以前我使用 subscribed 方法并且一切正常,但我决定使用异步管道重写代码,但它不起作用......
- RestAPI retursn requests in particular format
- RestAPI 以特定格式返回请求
export interface responseFormat {
success: boolean;
data: any;
}
- returned data can be in different types. In this particular case data returns restaurant object... It also might be arrays of different objects...
- 返回的数据可以是不同的类型。在这种特殊情况下,数据返回餐厅对象......它也可能是不同对象的数组......
export interface restaurant {
_id: string;
name: string;
description: string;
images: file[];
cuisines: cuisine[];
blocked: boolean;
created: Date;
business_hours: object;
}
- Previously I used the following code (it works):
- 以前我使用了以下代码(它有效):
/* Provider */
getRestaurant(): Observable<responseFormat> {
return this.http.get<responseFormat>(environment.api + "/restaurant");
}
/* Component */
private restaurant: restaurant;
getRestaurant() {
this.restaurantProvider.getRestaurant().subscribe(res => {
if (res.success) this.restaurant = res.data;
});
}
as a result the type of the variable is assigned.... But I don't want to keep the record of subscriptions thus I wanted to convert the code using Angular async pipe... This is what I've done... it doesn't works
结果分配了变量的类型......但我不想保留订阅的记录,因此我想使用Angular异步管道转换代码......这就是我所做的......它不起作用
/* Provider */
getRestaurant(): Observable<responseFormat> {
return this.http.get<responseFormat>(environment.api + "/restaurant");
}
/* Component */
private restaurantObservable: Observable<restaurant>;
getRestaurant() {
this.restaurantObservable = this.restaurantProvider.getRestaurant().map(res => <restaurant>res.data);
// or //
this.restaurantObservable = this.restaurantProvider.getRestaurant().map(res => res.data as restaurant);
}
But the above code doesn't cast the type of the response to the interface...
但是上面的代码并没有将响应的类型转换为接口......
What am I doing wrong???
我究竟做错了什么???
In other words I can get the Observable variables in template (with https://angular.io/api/common/AsyncPipe> like that:
换句话说,我可以在模板中获取 Observable 变量(使用https://angular.io/api/common/AsyncPipe> 像这样:
/* Provider */
getRestaurant(): Observable<responseFormat> {
return this.http.get<responseFormat>(environment.api + "/restaurant");
}
/* Component */
private restaurantObservable: Observable<restaurant>;
getRestaurant() {
this.restaurantObservable = this.restaurantProvider.getRestaurant().map(res => res.data as restaurant);
}
/* Template */
<div class="name">{{ (restaurantObservable | async)?.name }}</div>
// or //
<div *ngIf="restaurantObservable | async as restaurant">
<div>{{ restaurant.name }}</div>
</div>
But I can't get the property of the restaurant observable in component... For instance this.restaurant.cuisinesthrow the error "property cuisines does not exist on type Observable"
但是我无法在组件中获取可观察餐厅的属性......例如this.restaurant.cuisines抛出错误“属性菜系在 Observable 类型上不存在”
回答by Jeto
Why not directly return an Observable<restaurant>
from your service?
为什么不直接Observable<restaurant>
从您的服务中返回一个?
getRestaurant(): Observable<restaurant> {
return this.http.get<responseFormat>(environment.api + "/restaurant")
.map((response: responseFormat) => response.data as restaurant);
}
Then on component side:
然后在组件方面:
getRestaurant() {
this.restaurantProvider.getRestaurant().subscribe((res: restaurant) => {
this.restaurant = res;
});
}
The error handling (success
flag, HTTP errors, etc) could be handled via an HTTP Interceptor.
错误处理(success
标志、HTTP 错误等)可以通过HTTP Interceptor进行处理。
回答by Sammi
The Angular async template pipe subscribes to the Observable, that is how it is able to access the restaurant object and its properties in the template.
Angular 异步模板管道订阅了 Observable,这就是它如何能够访问模板中的餐厅对象及其属性。
If you want to access to these same thing in the component controller then you need to make a subscription in the component controller.
如果你想在组件控制器中访问这些相同的东西,那么你需要在组件控制器中进行订阅。
回答by ConsultingEasy
Given that your rest service or provider returns a Restaurant in this format (i've always used classes not interfaces, sorry i can't provide any help with this distinction, so in my example Restaurant is a class).
鉴于您的休息服务或提供者以这种格式返回餐厅(我一直使用类而不是接口,抱歉,我无法提供有关这种区别的任何帮助,因此在我的示例中,餐厅是一个类)。
export class Restaurant {
_id: string;
name: string;
description:
string; email:
{
address: string;
confirmation_code: string;
confirmed: boolean;
};
auth: {
password: string;
};
branches: Branch[];
menus: Menu[];
images: File[];
cuisines: Cuisine[];
blocked: boolean;
created: Date;
business_hours: object;
}
You should be able to have angular serialise the response for you as an example:
作为示例,您应该能够以角度序列化响应:
getRestaurant(): Observable<Restaurant> {
return this.http.get<Restaurant>(environment.api + "/restaurant");
}
That is given you also have a also imported the other types Branch, Menu, File, Cuisine into the typescript file containing the restaurant. for example branch would look like
也就是说,您还可以将其他类型的 Branch、Menu、File、Cuisine 导入包含餐厅的打字稿文件中。例如分支看起来像
export class Branch {
// branches properties
}