Наблюдаемый <{}> не присваивается типу Observable <SomeType []>
Я изучаю Angular2 и Typescript. Я работаю над учебником Heroes по angular.io, но применяю его к проекту, который я конвертирую из ASP.Net. Я столкнулся с проблемой, которая, как мне кажется, связана с моим недостатком понимания, хотя, насколько я вижу, она соответствует тому, что делает соответствующая часть учебника.
import { Injectable } from '@angular/core';
import {RiskListSummary} from '../Models/RiskListSummary';
import { Observable } from 'rxjs/Rx';
import { Http, Response } from '@angular/http';
@Injectable()
export class RiskAssessmentListService {
constructor(private http : Http) {}
private serviceUrl = "http://myserviceurl/";
getRisks(): Observable<RiskListSummary[]> {
return this.http.get(this.serviceUrl)
.map(this.extractData())
.catch(this.handleError());
}
private extractData(res: Response) {
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
let body = res.json();
return body.data || { };
}
private handleError (error: any) {
let errMsg = error.message || 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
}
Я получаю следующую ошибку в строке "return this.http.get(this.serviceUrl)":
Ошибка: (20, 16) TS2322: Тип 'Observable < {} > ' не присваивается типу "Наблюдаемая". Тип '{}' не присваивается типу 'RiskListSummary []. Длина свойства 'length' отсутствует в типе '{}'.
Если это имеет значение, я использую webstorm (последняя версия), но я думаю, что эта ошибка идет прямо из компилятора typescript. Я думал, может быть, мне нужен файл с типизацией для rxjs, но учебник не использует его, и ни один из тех, которые я нашел с помощью "поиска по типу", не изменил
Ниже приведены мои зависимости от package.json:
"dependencies": {
"@angular/common": "2.0.0-rc.1",
"@angular/compiler": "2.0.0-rc.1",
"@angular/core": "2.0.0-rc.1",
"@angular/http": "2.0.0-rc.1",
"@angular/platform-browser": "2.0.0-rc.1",
"@angular/platform-browser-dynamic": "2.0.0-rc.1",
"@angular/router": "2.0.0-rc.1",
"@angular/router-deprecated": "2.0.0-rc.1",
"@angular/upgrade": "2.0.0-rc.1",
"systemjs": "0.19.27",
"es6-shim": "^0.35.0",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "^0.6.12"
Ответы
Ответ 1
Я думаю, что ваша проблема находится здесь:
getRisks(): Observable<RiskListSummary[]> {
return this.http.get(this.serviceUrl)
.map(this.extractData()) <== passing result of function
.catch(this.handleError()); <== passing result of function
}
Вы можете использовать просто передачу ссылки на function
:
getRisks(): Observable<RiskListSummary[]> {
return this.http.get(this.serviceUrl)
.map(this.extractData)
.catch(this.handleError);
}
но так ты потеряешь this
.
Или вы можете использовать метод связывания, чтобы сохранить this
:
getRisks(): Observable<RiskListSummary[]> {
return this.http.get(this.serviceUrl)
.map(this.extractData.bind(this))
.catch(this.handleError.bind(this));
}
однако вы потеряете проверку типов.
Я хотел бы использовать функции стрелок, чтобы иметь возможность использовать лексическое это:
getRisks(): Observable<RiskListSummary[]> {
return this.http.get(this.serviceUrl)
.map(res => this.extractData(res))
.catch(err => this.handleError(err));
}
Без this
переменная this
будет указывать на функцию, в которой выполняется вызов, а не на экземпляр, содержащий getRisks()
.
Ответ 2
У меня была та же проблема, однако, как бы я ни менял, как это было сказано выше, она все еще не работает. Пока мой колледж не нашел эту карту, поймайте определение, как подсказал VSC
поэтому правильное изменение должно быть таким (добавить тип приведите в следующем месте)
getRisks(): Observable<RiskListSummary[]> {
return this.http.get(this.serviceUrl)
.map<RiskListSummary[]>(this.extractData)
.catch<RiskListSummary[]>(this.handleError);
}
Я новичок в TypeScript. так что этот вид [подписи метода] действительно дает мне молоток по голове :(
Но в итоге все получилось :)
Ответ 3
В соответствии с getRisks()
fn вы возвращаете типы Observable<RiskListSummary[]>
. Однако в вашем коде вы возвращаете body.data || {}
. Я считаю, что вам нужно связать свой RiskListSummary [] с вашим body.data.
Ответ 4
Я обнаружил следующее: AccessTokens отсутствовал. Итак, я внес изменение, и оно сработало: на вашей модели (в моем случае Country) отредактируйте файл de и измените его с:
export interface CountryInterface {
"id"?: any;
"name": string;
"order"?: number;
}
export class Country implements CountryInterface {
"id": any;
"name": string;
"order": number;
....
}
Для того, чтобы:
export interface CountryInterface {
"id"?: any;
"name": string;
"order"?: number;
accessTokens: any[];
}
export class Country implements CountryInterface {
"id": any;
"name": string;
"order": number;
accessTokens: any[];
...
}
Ответ 5
Typescript - это инструмент компилятора, который всегда будет давать ошибку компиляции типа, так как здесь метод getRisk должен указывать, что он возвращается. Наблюдаемый тип RiskListSummary, так что инструмент должен распознавать, что ожидается из этого метода и проверит безопасность типа при использовании в методе подписки.