0

Hi there I am learning angular with version 6. I am trying to map a basic http response and return in an Observable, however, I am getting this type casting error.

market-data.component.ts

import { Component, OnInit, Inject } from "@angular/core";
import { MarketDataService } from "./market-data.service";
import { CoinMarketCapTokenEntity } from "../entity/coinmarketcaptoken-entity";

@Component({
    selector: "app-market-data",
    templateUrl: "./src/app/market-data.component.html"
})
export class MarketDataComponent implements OnInit {
    private _marketDataService: MarketDataService;
    private _tokens: CoinMarketCapTokenEntity[];

    constructor(marketDataService: MarketDataService) {
        this._marketDataService = marketDataService;
    }

    ngOnInit() {
        this._tokens = this._marketDataService.getCoinMarketCapTokens();
    }
}

market-data-service

import { Injectable } from "@angular/core";
import { Http, Response, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { CoinMarketCapTokenEntity } from "../entity/coinmarketcaptoken-entity";

const coinMarketcapCoinsUrl = "https://s2.coinmarketcap.com/generated/search/quick_search.json";

@Injectable()
export class MarketDataService {
    private _http: Http;

    constructor(http: Http) {
        this._http = http;
    }

    getCoinMarketCapTokens(): Observable<CoinMarketCapTokenEntity[]> {
        return this._http.get(coinMarketcapCoinsUrl, {headers: this.getHeaders()})
                               .map(this.mapTokens);
    }

    mapTokens(response: Response): CoinMarketCapTokenEntity[] {
        return response.json().map(this.toCoinMarketCapToken);
    }

    toCoinMarketCapToken(r: any): CoinMarketCapTokenEntity {
        let token = <CoinMarketCapTokenEntity>({
            name: r.name,
            symbol: r.symbol,
            rank: r.rank,
            slug: r.slug,
            tokens: r.tokens,
            id: r.id
        });
        return token;
    }

    getHeaders() {
        let headers = new Headers();
        headers.append("Accept", "application/json");
        return headers;
    }
}

and the error I am having is

src/app/market-data.component.ts(18,9): error TS2322: Type 'Observable<CoinMarketCapTokenEntity[]>' is not assignable to type 'CoinMarketCapTokenEntity[]'.
[1]   Property 'length' is missing in type 'Observable<CoinMarketCapTokenEntity[]>'

I also checked the duplicate question here - Observable<{}> not assignable to type Observable<SomeType[]>

however none of the solutions worked. Thanks for your help

quartaela
  • 2,579
  • 16
  • 63
  • 99

3 Answers3

1

You just use subscribe method to convert observable model to your model.

baj9032
  • 2,414
  • 3
  • 22
  • 40
1

You are mixing old version and new version coding style. There are few things, you should change into your code, 1. You should use HttpHeaders(can be imported from @angular/common/http) instead headers. 2. There is no need to call map on response from your web service like you did in

return this._http.get(coinMarketcapCoinsUrl, {headers: this.getHeaders()})
                           .map(this.mapTokens);

http.get() itself returns Observable. For retrieving data from Observable you can use subscribe() method on it.

  1. There is no need to call map on response, like you did in your code

    return response.json().map(this.toCoinMarketCapToken);

    response.json() will give you a Promise object, and Promise object does not have map method. You have to call then() method to retrieving data from it.

Kuldeep Singh
  • 199
  • 1
  • 11
  • oh cool! I didnt know this. There are so many examples on the web about angular so finding the most latest one is hard. Let me try this right away – quartaela Jun 14 '18 at 05:23
  • You can refer [link](https://www.ktechlabs.com/2018/06/angular-webservice-integration.html) , it will help you to play around with the data received from your webservice. – Kuldeep Singh Jun 14 '18 at 07:17
1

The below code works.

import { Injectable } from "@angular/core";
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
const coinMarketcapCoinsUrl = "https://s2.coinmarketcap.com/generated/search/quick_search.json";

@Injectable()
export class MarketDataService {

    constructor(private _http: HttpClient) {

    }
    getCoinMarketCapTokens(): Observable<CoinMarketCapTokenEntity[]> {
          return this._http.get<CoinMarketCapTokenEntity[]>(coinMarketcapCoinsUrl);
    }

}

export class CoinMarketCapTokenEntity{
    name;
    symbol;
    rank;
    slug;
    tokens;
    id;
}
Rakesh M R
  • 242
  • 2
  • 7
  • Welcome to Stack Overflow! Please don't just throw your source code here. Be nice and try to give a nice description to your answer, so that others will like it and upvote it. See: [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) – sɐunıɔןɐqɐp Jun 14 '18 at 06:50
  • hey thanks for the response, however, I am getting /node_modules/@angular/common/http.js not found on client side. I did a small research I think I also need to import HttpModule in Module package as well. – quartaela Jun 14 '18 at 07:27