Observable<Any> 转换为 Observable<Bar[]>

huangapple go评论74阅读模式
英文:

Observable<Any> transformation to Observable<Bar[]>

问题

我对Angular还相对新手,我试图将Observable的结果转换为Observable<Bar[]>,但我遇到了一个错误:类型Bar不能赋值给类型'ObservableInput'

find(id: string): Observable<Bar[]> {
    return this.findFoo(id)
        .pipe(
          map(data => data.result.entities),
          switchMap((data) => {
            let bar: Bar[] = [{
              id: data.field,
              entity: data
            }];
            return of(bar);
          })
        );
}

有什么办法可以解决吗?

英文:

I'm pretty new to angular, I'm trying to transform result of an Observable any to Observable<Bar[]> but I have an error: Type Bar is not assignable to type 'ObservableInput any

find(id: string): Observable&lt;Bar[]&gt; {
    return this.findFoo(id)
        .pipe(
          map(data =&gt; data.result.entities)
          switchMap((data) =&gt; {
            let bar: Bar = {
              id: data.field,
              entity: data
            };
            return bar;
          })
        );
}

Any idea how to do ?

答案1

得分: 1

switchMap 操作符应该返回一个可观察对象。在你的情况下,实际上不需要它。你可以在你的 map 操作符上指定类型,它会应用投影并发出结果。类似这样:

find(id: string): Observable<Bar[]> {
    return this.findFoo(id)
        .pipe(
            map((data: any) => data.result.entities)
        );
}

这里有一个示例 stackblitz

编辑:关于映射到不同的字段 - 使用实际数组上的 map 方法应该基本相同(注意 - 在数组上,而不是可观察对象上),例如:

find(id: string): Observable<Bar[]> {
    return this.findFoo(id)
        .pipe(
            map((data: any) => data.result.entities.map(x => {
                return { id: x.bar, label: x.foo }
            }))
        );
}

从这个评论中更新的 stackblitz 在 这里

英文:

The switchMap operator should return an observable. You don't really need it in your case. You can just specify type on your map operator, which will apply the projection and emit the results. Something like this:

find(id: string): Observable&lt;Bar[]&gt; {
    return this.findFoo(id)
        .pipe(
          map(data&lt;any, Bar[]&gt; =&gt; data.result.entities)
        );
}

Here's a sample stackblitz.

EDIT: Regarding mapping to different fields - it should be pretty much the same with included map method on the actual array (note - on the array, not observable), e.g.

find(id: string): Observable&lt;Bar[]&gt; {
    return this.findFoo(id)
        .pipe(
          map(data&lt;any, Bar[]&gt; =&gt; data.result.entities.map(x =&gt; {
            return {id: x.bar, label: x.foo}
          })
        );
}

Updated stackblitz from the comment here.

答案2

得分: 1

只需将您的switchMap更改为map

find(id: string): Observable<Bar[]> {
    return this.findFoo(id)
        .pipe(
          map((data: Foo) => data.result.entities),
          map((entities: FooEntity[]) => {
            return entities.map((entity: FooEntity) => {
              const bar: Bar = {
                id: entity.field,
                entity: entity
              };
              return bar;
            });
          })
        );
}

然后,您也可以合并这两个map

find(id: string): Observable<Bar[]> {
    return this.findFoo(id)
        .pipe(
          map((data: Foo) => data.result.entities.map((entity: FooEntity) => {
            const bar: Bar = {
              id: entity.field,
              entity: entity
            };
            return bar;
          }))
        );
}
英文:

just change your switchMap to a map:

find(id: string): Observable&lt;Bar[]&gt; {
    return this.findFoo(id)
        .pipe(
          map((data: Foo) =&gt; data.result.entities),
          map((entities: FooEntity[]) =&gt; {
            return entities.map((entity:FooEntity) =&gt; {
              const bar: Bar = {
                id: entity.field,
                entity: entity
              };
              return bar;
            });
          })
        );
}

then you can also combine those 2 maps:

find(id: string): Observable&lt;Bar[]&gt; {
    return this.findFoo(id)
        .pipe(
          map((data: Foo) =&gt; data.result.entities.map((entity: FooEntity) =&gt; {
            const bar: Bar = {
              id: entity.field,
              entity: entity
            };
            return bar;
          }))
        );
}

答案3

得分: 0

按照以下方式执行,以符合 Typescript 规范 👌🏼:

find(id: string): Observable<Array<Bar>> {
    return this.findFoo(id)
        .pipe(
            map((response: Array<any>) => {
                return response.result.entities.map((entity: any) => {
                    return {
                        id: entity.field,
                        entity: entity
                    } as Bar
                })
            })
        );
}

顺便问一下,为什么 find 方法返回 (Array of) any?这不能像这样保证类型安全吗?

英文:

Do it like so to be Typescript compliant 👌🏼:

find(id: string): Observable&lt;Array&lt;Bar&gt;&gt; {
    return this.findFoo(id)
        .pipe(
          map((response: Array&lt;any&gt;) =&gt; {
            return response.result.entities.map((entity: any) =&gt; {
              return {
                id: entity.field,
                entity: entity
              } as Bar
            }
          }
        );
}

By the way, why does the find method return (Array of) any? Couldn't this be type safe as well?

答案4

得分: -1

你的函数返回Observable<Bar[]>,因此在你的语句中也必须返回这种类型,如下所示:

let bars: Bar[] = [];
bars.push(bar);

return of(bars);
英文:

Since your function returns Observable&lt;Bar[]&gt;, you have to return in your statement also this type like so:

let bars: Bar[] = [];
bars.push(bar);

return of(bars);

huangapple
  • 本文由 发表于 2023年6月19日 15:48:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76504606.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定