RxJS 分区。错误 - 类型中缺少以下属性

RxJS partition. ERROR - is missing the following properties from type

有代码:

    ngOnInit(): void {
        [this.newReleaseNotes$, this.readReleaseNotes$] = partition(this.getReleaseNotes$(), ({ id }: ReleaseNoteInterface) =>
            this.releaseNotesService.readReleaseNotes.includes(id),
        );
    }

    private getReleaseNotes$(): Observable<ReleaseNoteInterface[]> {
        return forkJoin(this.releaseNotes.map((releaseNoteId: string) => this.releaseNotesService.fetchReleaseNoteById$(releaseNoteId)));
    }

此代码在 TypeScript 中引发错误:

error TS2345: Argument of type '({ id }: ReleaseNoteInterface) => boolean' is not assignable to parameter of type '(value: ReleaseNoteInterface[], index : number) => boolean'. [0] Types of parameters '__0' and 'value' are incompatible. [0] Type 'ReleaseNoteInterface[]' is missing the following properties from type 'ReleaseNoteInterface': id, type, importance, actuality, and 8 more.

方法this.releaseNotesService.fetchReleaseNoteById$向服务器发出请求并且returnsObservable<ReleaseNoteInterface>

如何正确使用分区运算符来解决我的问题?

forkJoin 发出其内部可观察值的数组,因此 partition 期望类型 ReleaseNoteInterface[],而不是类型 ReleaseNoteInterface.

因此您的 partition 必须对该数组进行操作:

    partition(this.getReleaseNotes$(), (releaseNotes: ReleaseNoteInterface[]) =>
        // unclear what to do with the array here?
        releaseNotes.some(({id}) => this.releaseNotesService.readReleaseNotes.includes(id))
    );

这将创建两个可观察流,一个是数组中的任何 id 满足条件,另一个是数组中 none 个 id 满足条件。怀疑这就是你想要的

partition 用于将可观察流拆分为 2 个流。虽然 forkJoin 是一个更高阶的可观察对象,用于将多个可观察对象合并为一个,并且 forkJoin 根据定义只会发出一次,并且一旦所有内部观察对象完成,它将发出一个包含所有内部可观察对象的数组。因此,在 forkJoin 上使用 partition 是不合逻辑的,因为存在 partition 来拆分多个排放流,而 forkJoin 只是一个可观察到的排放。

您可能想要做的是:

ngOnInit(): void {
   const sharedNotes$ = this.getReleaseNotes$(); // get the sahred

   this.newReleaseNotes$ = sharedNotes$.pipe( // map and filter the array
     map(releaseNotes => releaseNotes.filter(({id}) => this.releaseNotesService.readReleaseNotes.includes(id)))
   )

   this.readReleaseNotes$ = sharedNotes$.pipe( // map and filter the array
     map(releaseNotes => releaseNotes.filter(({id}) => !this.releaseNotesService.readReleaseNotes.includes(id)))
   )

}

private getReleaseNotes$(): Observable<ReleaseNoteInterface[]> {
    return forkJoin(this.releaseNotes.map((releaseNoteId: string) => this.releaseNotesService.fetchReleaseNoteById$(releaseNoteId))).pipe(
      share() // share it to avoid multiple calls
    );
}

这为您提供了两个可观察对象,两个版本说明数组,一个包含满足条件的项目,另一个包含不满足条件的项目。

还有其他合乎逻辑的方法来设置它,比如只有一个符合接口 { newReleaseNotes: ReleaseNoteInterface[], readReleaseNotes: ReleaseNoteInterface[] } 的可观察对象并使用 map 运算符转换成那个。

@bryan60,感谢您的解释!做了一点不同:

    ngOnInit(): void {
        this.newReleaseNotes$ = this.getReleaseNotes$(this.releaseNotes.filter((id: string) => !this.releaseNotesService.readReleaseNotes.includes(id)));
        this.readReleaseNotes$ = this.getReleaseNotes$(this.releaseNotes.filter((id: string) => this.releaseNotesService.readReleaseNotes.includes(id)));
    }

    private getReleaseNotes$(releaseNotesIds: string[]): Observable<ReleaseNoteInterface[]> {
        return forkJoin(releaseNotesIds.map((releaseNoteId: string) => this.releaseNotesService.fetchReleaseNoteById$(releaseNoteId)));
    }

本来我只是想用partion功能漂亮的解决这个问题。 也许有一个选项可以用 partion 可以使用的其他东西替换 forkJoin