Я создал очень простое приложение на основе учебника Angular2.
Для начала у меня есть очень простая модель "Книга":
/**
* book model
*/
export class Book {
public data;
/**
* constructor
* @param id
* @param title
* @param pages
*/
constructor(
public id,
public title:string,
public pages:Array
){
alert('it works'); // just a check
}
}
К себе на службу попала такая книга:
return this._http.get('getBook/1')
.map(function(res){
return <Book> res.json();
})
Я ожидал, что это приведет к получению результирующих данных JSON и «сопоставит» их с объектом Book.
Однако он просто возвращает объект с типом «Object».
Я мог бы сам создать новый объект Book и передать параметры в конструктор, например:
return new Book(res.id, res.title, res.pages);
Это лучший способ сделать это? Я что-то пропустил?
4 ответа
Да, приведение объекта к типу в TypeScript не создает экземпляр этого типа. Это просто средство TypeScript для проверки типов.
Если вам действительно нужен экземпляр Book
, вам нужно использовать что-то вроде этого:
return this._http.get('getBook/1')
.map(function(res){
var data = res.json();
return new Book(data.id, data.title, data.pages);
})
Чтобы ответить на ваш вопрос . Фактически, если у вас есть только поля в вашем типе (например, с интерфейсом), достаточно литья. Более того, если у вас есть методы, которые вы хотите использовать позже, необходимо неявно создать экземпляр типа Book
(см. Выше) вместо приведения. В противном случае вы не сможете их использовать (они не будут определены на вашем объекте) ...
См. Этот вопрос для получения более подробной информации:
Из https://angular.io/guide/http#requesting-a-typed -ответ
Чтобы указать тип объекта ответа, сначала определите интерфейс с необходимыми свойствами. Используйте интерфейс, а не класс, потому что ответ представляет собой простой объект, который не может быть автоматически преобразован в экземпляр класса.
Всегда получайте ответ через интерфейс, потому что происходит только отображение полей, и вы не можете использовать класс, если у вас есть функция экземпляра, которая выдает ошибку при использовании этого объекта.
product.getPrice is not a function
Пример
interface ProductInterface {
id: number;
name: string;
price: number;
}
class Product implements ProductInterface {
id: number;
name: string;
price: number;
constructor(productData: ProductInterface) {
this.id = product.id;
this.name = product.name;
this.price = product.price;
}
public getPrice(): string {
return this.price + " INR";
}
}
class ProducService {
...
...
getProduct(): Observable<Product> {
return this.http.get<Product>('assets/product.json').pipe(map(data => new Product(data)));
}
getProductWithoutMappingToClass(): Observable<Product> {
return this.http.get<Product>('assets/product.json');
} // Throw runtimerror ctx_r1.product.getPrice is not a function
}
Хорошая практика - использовать данные из ответа GET, используя
Observable<Model>
(относительно документации Angular https://angular.io/guide/http) А потом:
// импорт
import {HttpClient} from "@angular/common/http";
// в списке параметров конструктора
private http: HttpClient
// сервисный метод
getBook(): Observable<Book> {return this.http.get<Book>({url}, {options});}
Я думаю, вам следует объявить интерфейс Book
вместо класса book
:
export interface Book {
public id;
public title:string;
public pages:Array;
}
К вашим услугам:
//get one record
return this._http.get('getBook/1')
.map(function(res){
return <Book> res.json();
});
//get multi record
return this._http.get('getBooks')
.map(function(res){
return <Book> res.json();
});
Похожие вопросы
Связанные вопросы
Новые вопросы
angular
Вопросы об Angular (не путать с AngularJS), веб-фреймворке от Google. Используйте этот тег для вопросов Angular, которые не относятся к отдельной версии. Для более старой веб-инфраструктуры AngularJS (1.x) используйте тег AngularJS.