ReactiveX / ReactiveX/rxjs

[combineLatest] loses the tuple shape of array-literal sources, unlike [forkJoin]

Open Beginner friendly
#7,637 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
31.7k
Forks
3k
PR merge metrics
No merged PRs in 30d

Description

Describe the bug

For a: Observable<number> and b: Observable<string>, Observable[combineLatest]([a, b]) returns Observable<(string | number)[]>. Destructured values cannot be assigned to number and string variables.

Observable[forkJoin]([a, b]) returns Observable<[number, string]> and the same assignments compile.

Expected behavior

Save the following as repro.ts in an empty directory, then run:

npm install rxjs@9.0.0-beta.0 typescript@6.0.3
npx tsc --strict --lib esnext,dom --moduleResolution bundler --module preserve --declaration repro.ts
import "rxjs"
import { combineLatest } from "rxjs/combine-latest"
import { forkJoin } from "rxjs/fork-join"

declare const a: Observable<number>
declare const b: Observable<string>

export const cl = Observable[combineLatest]([a, b])
export const fj = Observable[forkJoin]([a, b])

cl.subscribe(([n, s]) => { const x: number = n; const y: string = s })  // errors
fj.subscribe(([n, s]) => { const x: number = n; const y: string = s })  // ok

Relevant declaration output and diagnostics:

export declare const cl: Observable<(string | number)[]>;
export declare const fj: Observable<[number, string]>;

repro.ts(11,34): error TS2322: Type 'string | number' is not assignable to type 'number'.
  Type 'string' is not assignable to type 'number'.
repro.ts(11,55): error TS2322: Type 'string | number' is not assignable to type 'string'.
  Type 'number' is not assignable to type 'string'.

Expected: the result preserves each position's type (number, then string), and both subscriptions compile.

Reproduction code

Reproduction URL

No response

Version

rxjs 9.0.0-beta.0

Environment

TypeScript 6.0.3 with strict. Same result with vue-tsc 3.3.11.

Additional context

Observable[combineLatest]([a, b] as const) returns Observable<readonly [number, string]> and the assignments compile.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the TypeScript declarations behind the rxjs/combine-latest entry point and compare them with rxjs/fork-join, using the provided repro.ts and compiler command. The work is done when Observable[combineLatest]([a, b]) preserves the [number, string] tuple shape without as const and the two assignments compile under strict TypeScript.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
developer-experience
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.