1

I have this problem. I have an interface called Person which has a optional key called asked. I need to pass an array of that interface to a function which return an observable of type Person[] using RXJS.


interface Person {
    name string;
    asked?: boolean;
}

const persons: Person[] = [
    {name: "Wako"},
    {name: "Yako"},
    {name: "Dot"},
];

const persons$ = (persons: Person[]): Observable<Person[]> {
    return of(persons).pipe(
        map((p: Person) => {
            p.asked = true;
            return p;
        })
    );
}

But I have this problem:

Type 'Observable<Person>' is not assignable to type 'Observable<Person[]>'.
  Type 'Person' is missing the following properties from type 'Person[]': length, pop, push, concat, and 16 more.ts(2322)

What does my function persons$ has to do to return a Observable<Person[]>.

4
  • 1
    You seem to be confusing an observable map with an array map. You probably want both: map((people) => people.map((person) => ({ ...person, asked: true }))). Commented Nov 11, 2020 at 23:55
  • This would be inside the pipe? Because I need to do it using rxjs. Commented Nov 12, 2020 at 0:00
  • 1
    Yes, that would be inside the pipe. map is from RxJS, Array#map is not. Commented Nov 12, 2020 at 0:01
  • Thank you! I was using the map of rxjs as a regular map. This solved my problem. Thanks Commented Nov 12, 2020 at 6:39

2 Answers 2

3

You can do it with another solution:

import { from, Observable } from "rxjs";
import { map, toArray } from "rxjs/operators";

interface Person {
  name: string;
  asked?: boolean;
}

const persons: Person[] = [
  { name: "Wako" },
  { name: "Yako" },
  { name: "Dot" },
];

const persons$ = (persons: Person[]): Observable<Person[]> => {
  return from(persons).pipe(
    map((p: Person) => ({ ...p, asked: true })),
    toArray(),
  );
};

persons$(persons)
  .subscribe((x) => console.log(x));
Sign up to request clarification or add additional context in comments.

Comments

1

Observable.of(...args) will always unwrap the array and turn into Observable<Person>. If you want an Observable<Person[]> you need to do something like:

const persons$ = (persons: Person[]): Observable<Person[]> {
    return of(persons).pipe(
        map((people: Person[]) => people.map(p => ({...p, asked: true})))
    );
}

3 Comments

Thank you! I was using the rxjs map as a regular map, but now I can see the difference.
Only if they'd done of(...persons) would each person be emitted separately; it's from that emits array elements one-by-one. I think what you show now would emit an array containing an array.
You're right @jonrsharpe, I think the actual error was from OP's wrong typecasting in the map operator, declaring the callback as (person: Person) => instead of (person: Person[]) =>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.