【问题标题】:Correctly inferring types when chaining observables链接可观察对象时正确推断类型
【发布时间】:2017-03-08 01:43:39
【问题描述】:

我有一个 Angular2 应用程序,它具有获取项目列表的服务。还有一种方法可以为列表中的每个项目获取更具体的信息。我目前的设置是:

// service for item list
class ItemsService {
  fetchItems(): Observable<Item[]> {
    return this.http.get(url).map((res: Response) => res.json());
  }
  fetchItemsWithData(): Observable<Item[]> {
    return this.fetchItems()
    .flatMap((items: Observable<Item[]>) => items)
    .map((item: Item) => this.itemService.fetchData(item))
    .flatMap((items: Observable<Item[]>) => items)
    .toArray();
  }
}

// service for individual items
class ItemService {
  fetchData(item: Item) {
    return this.http.get(`${url}/${item.id}`)
    .map((res: Response) => res.json());
  }
}

这实际上完全按照我的需要工作,尽管数组 observable 看起来有点时髦,但它最终给了我一个包含所有项目信息的项目数组的 observable。

问题是,在return this.fetchItems() 行我总是得到:

The type argument for type parameter 'T' cannot be inferred from the usage.
Consider specifying the type arguments explicitly.
  Type argument candidate 'Item[]' is not a valid type argument because it is not a
  supertype of candidate 'Observable<Item[]>'.
    Property 'length' is missing in type 'Observable<Item[]>'.

我有点不知所措,因为 fetchItems 确实返回了 Observable 并将其更改为 Observable&lt;any&gt; 给出了相同的错误。如果我只是将其更改为 any 虽然我根本没有收到任何错误报告。

fetchItems 有更好的类型吗?

【问题讨论】:

    标签: angular typescript rxjs


    【解决方案1】:

    当我遇到同样的问题时,原因是我忘记导入Response 类:

    import { Http, Response } from '@angular/http';

    希望对某人有所帮助。

    【讨论】:

    • 操!这只是发生在我身上,它发生在我太信任 WebStorm 之后 - WebStorm 没有自动添加它,我什至没有检查... :-)
    • @BoazRymland 是的,这很奇怪,它甚至没有警告使用未导入的类
    【解决方案2】:

    我怀疑这可能与返回 Observable&lt;T[]&gt;toArray() 有关。

    在您定义fetchItems(): Observable&lt;Item[]&gt; 的情况下,它使toArray() 返回Observable&lt;Observable&lt;Item[]&gt;[]&gt;,这就是为什么即使使用Observable&lt;any&gt; 也会引发错误。

    顺便说一句,我尝试仅使用模拟类来模拟您的情况,并且编译时没有错误(TypeScript 2.0.3),但也许我在某处出错并且不完全相同(?):

    class Observable<T> {
        map(_): Observable<T> { return new Observable<T>() }
        flatMap(_): Observable<T> { return new Observable<T>() }
        toArray(): Observable<T[]> { return new Observable<T[]>() }
    }
    class Item { }
    class Response {
        json() { }
    }
    class HTTP {
        get(_) { return new Observable() }
    }
    
    
    class ItemsService {
        itemService = new ItemService();
        http = new HTTP();
    
        fetchItems(): Observable<Item[]> {
            return this.http.get('url').map((res: Response) => res.json());
        }
    
        fetchItemsWithData(): Observable<Item[]> {
            return this.fetchItems()
                .flatMap((items: Observable<Item[]>) => items)
                .map((item: Item) => this.itemService.fetchData(item))
                .flatMap((items: Observable<Item[]>) => items)
                .toArray();
        }
    }
    
    // service for individual items
    class ItemService {
        http = new HTTP();
    
        fetchData(item: Item) {
            return this.http.get('url')
                .map((res: Response) => res.json());
        }
    }
    

    【讨论】:

      【解决方案3】:

      尝试将返回的类型信息添加到您的地图并更改您的数组注释:

      1. 请使用Array&lt;Item&gt;,而不是Item[]
      2. fetchData(item: Item): ItemData.map((item: Item): ItemData =&gt; this.itemService.fetchData(item))

      【讨论】:

        猜你喜欢
        • 2018-01-10
        • 2015-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-26
        • 2018-10-25
        • 2018-06-07
        • 1970-01-01
        相关资源
        最近更新 更多