You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RxJS+TypeScript中merge与scan搭配使用的类型处理优化方案

RxJS merge+scan 类型安全优化方案

现存问题

  • 类型层面:merge合并的两个流输出类型不统一,一个返回Process[](服务端全量列表),一个返回单个Process(本地新增条目),合并后流类型为Observable<Process | Process[]>;累加器combineProcesses未做类型标注,靠运行时Array.isArray做兼容,丢失类型安全;且scan未传初始值,首次执行累加器时入参类型不可控。
  • 逻辑层面:现有累加器不区分全量拉取和增量新增场景,路由切换触发switchMap重新拉取全量列表时,会把新列表直接拼接到旧累加值后面,导致列表出现大量重复数据。
  • 代码层面:存在隐式any类型(比如routes$定义为Observable<any>、getProcesses未声明返回类型),累加器存在冗余的数组判断逻辑。

优化实现

采用判别式联合类型标记两类更新操作,给scan明确指定泛型类型与初始值,从根源锁定输出类型为Observable<Process[]>,同时修复重复数据bug:

// 定义列表操作的判别式联合类型,保证类型收窄安全
type ProcessListUpdate = 
  | { type: 'replace'; payload: Process[] }
  | { type: 'append'; payload: Process };

class ProcessService {
    processes$: Observable<Process[]>;
    private newProcess$ = new Subject<Process>();
    private routes$: Observable<string>; // 替换any为实际路由参数类型

    ngOnInit(): void {
        this.processes$ = merge(
            // 服务端全量拉取流:标记为替换操作
            this.routes$.pipe(
                switchMap(route => this.getProcesses(route)),
                map(processList => ({
                    type: 'replace' as const,
                    payload: processList
                }))
            ),
            // 本地新增流:标记为追加操作
            this.newProcess$.pipe(
                map(newProcess => ({
                    type: 'append' as const,
                    payload: newProcess
                }))
            )
        ).pipe(
            // 明确scan的输入、输出类型,传入初始空数组
            scan<ProcessListUpdate, Process[]>((acc, update) => {
                switch (update.type) {
                    case 'replace':
                        // 全量场景直接替换为服务端返回的新列表
                        return [...update.payload];
                    case 'append':
                        // 增量场景追加新条目到现有列表
                        return [...acc, update.payload];
                    default:
                        return acc;
                }
            }, [])
        );
    }

    private getProcesses(client: string): Observable<Process[]> {
        // 补全返回类型,实际业务中为HTTP请求
        return of([] as Process[]);
    }

    addNewProcess(process: Process): void {
        this.newProcess$.next(process);
    }
}

方案优势

  • 完全通过TypeScript类型校验:processes$类型自动推断为Observable<Process[]>,无隐式any,不需要运行时做数组类型判断,类型系统会自动校验累加器的分支处理是否覆盖所有操作类型。
  • 修复原逻辑的重复数据问题:明确区分全量替换和增量追加逻辑,路由切换拉取新列表时不会拼接旧数据。
  • 可扩展性强:后续新增删除、编辑流程的需求时,只需要在ProcessListUpdate中新增对应操作类型,在累加器中添加处理分支即可,维护成本低。
  • 职责清晰:源流只负责产出操作标记和对应数据,累加器统一处理状态更新,没有冗余判断逻辑。

内容的提问来源于stack exchange,提问作者Mr. Gung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:51:27