ReactiveX/rxjs

RxJS wrongly infers the type after using map operator with forkjoin

ernest-rudnicki opened this issue · 2 comments

Describe the bug

Hey there. I wonder if this is some limitation or Typescript or just a bug in RxJS

I am using forkJoin that has two observables with arrays (itemsA, itemsB) that have different types. Then I am using a pipe with map to add additional item to itemsA array and return both arrays as the tuple [itemsA, itemsB]. After that I subscribe to the forkJoined observable and try to assign one of the arrays to the new variable called allA that has type explicitly set to ItemA[]. However, TypeScripts shows the error, that it is not assignable, because both arrays in the tuple have now ItemA[] | ItemB[].

Type 'ItemA[] | ItemB[]' is not assignable to type 'ItemA[]'.
  Type 'ItemB[]' is not assignable to type 'ItemA[]'.
    Property 'propA' is missing in type 'ItemB' but required in type 'ItemA'.(

Expected behavior

The first item of the tuple should have the type ItemA[] and the second item should haveItemB[].

Reproduction code

import { forkJoin, of, map } from 'rxjs';


interface ItemA {
  propA: string;
}

interface ItemB {
  propB: string;
}

const itemsA: ItemA[] = [{propA: 'asd'}, {propA: 'bcd'}]
const itemsB: ItemB[] = [{propB: 'asd'}, {propB: 'bcd'}]
let allA: ItemA[] = []

forkJoin([of(itemsA), of(itemsB)]).pipe(map(([a, b]) => {
  a.push({propA: 'cdf'})

  return [a, b]
})).subscribe(([a, b]) => {
  allA = a // here is where the error happens
})

Reproduction URL

https://stackblitz.com/edit/typescript-nayvqr?file=index.ts

Version

7.8.1

Environment

No response

Additional context

No response

voliva commented

Not a RxJS issue, but it's how typescript works.

Typescript thinks your map is returing an Array<ItemA | ItemB>. Sort like if you do return [1,2,3] it will say that the function returns Array<number> instead of [number, number, number].

You have to explicitely tell it it's a tuple type for this to work. Either const result: [ItemA, ItemB] = [a,b]; return result; or return [a,b] as const

Thanks for help! Looks like it can be closed then