web-dev-qa-db-fra.com

Observable <{}> non assignable au type Observable <SomeType []>

J'apprends Angular2 et TypeScript. Je travaille sur le didacticiel Heroes sur angular.io, mais je l'applique à un projet que je convertis à partir d'ASP.Net. J'ai rencontré un problème qui, à mon avis, est dû à mon manque de compréhension, bien que, à ma connaissance, il corresponde à ce que la partie pertinente du tutoriel fait.

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);
    }
}

Je reçois le message d'erreur suivant sur la ligne "return this.http.get (this.serviceUrl)":

Erreur: (20, 16) TS2322: le type 'Observable <{}>' n'est pas assignable au type 'Observable'. Le type '{}' n'est pas assignable au type 'RiskListSummary []'. La propriété 'longueur' est manquante dans le type '{}'.

Si cela fait une différence, j'utilise webstorm (dernière version), mais je pense que cette erreur vient directement du compilateur TypeScript. Je pensais que j'avais peut-être besoin d'un fichier de typage pour rxjs, mais le tutoriel n'en utilise pas, et aucun de ceux que j'ai trouvés avec une "recherche de typage" n'a fait de différence.

Voici les dépendances de 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"
33
Kevin O'Donovan

Je pense que votre problème est situé ici:

getRisks(): Observable<RiskListSummary[]> {
  return this.http.get(this.serviceUrl)
     .map(this.extractData()) <== passing result of function
     .catch(this.handleError()); <== passing result of function
}

Vous pouvez simplement passer function reference:

getRisks(): Observable<RiskListSummary[]> {
  return this.http.get(this.serviceUrl)
     .map(this.extractData)
     .catch(this.handleError);
}

mais de cette façon, vous perdrez this.

Ou vous pouvez utiliser la méthode bind pour conserver this:

getRisks(): Observable<RiskListSummary[]> {
  return this.http.get(this.serviceUrl)
    .map(this.extractData.bind(this))
    .catch(this.handleError.bind(this));
}

cependant, vous allez perdre la vérification du type .

Je voudrais utiliser flèche fonctions pour pouvoir utiliser lexical cela :

getRisks(): Observable<RiskListSummary[]> {
  return this.http.get(this.serviceUrl)
    .map(res => this.extractData(res))
    .catch(err => this.handleError(err));
}

Sans elle, la variable this pointe vers la fonction où l'appel est effectué, au lieu de l'instance contenant getRisks().

26
yurzui

J'ai eu le même problème, mais peu importe comment j'ai changé comme mentionné ci-dessus, cela ne fonctionne toujours pas. Jusqu'à ce que mon collège trouve ceci carte, définition de capture à l'invite de VSC

le changement approprié devrait donc ressembler à (ajouter le type cast à la place suivante)

getRisks(): Observable<RiskListSummary[]> {
  return this.http.get(this.serviceUrl)
    .map<RiskListSummary[]>(this.extractData)
    .catch<RiskListSummary[]>(this.handleError);
}

Je suis nouveau sur TypeScript. donc ce genre de [méthode signature] me donne vraiment un marteau sur la tête :(

Mais finalement ça a marché :)

5
Fei

Selon la fonction getRisks()fn, vous êtes du type à renvoyer Observable<RiskListSummary[]>. Cependant, dans votre code, vous retournez body.data || {}. Je crois que vous devez interfacer votre RiskListSummary [] avec votre corps.data.

1
Sean Larkin

J'ai trouvé le suivant: AccessTokens avait disparu. Donc, j'ai fait le changement et cela a fonctionné: Sur votre modèle (dans mon cas, Pays), éditez le fichier et changez 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[];
  ...
}
1
Sergio Ibanez