1

I'm having a problem where I'm getting an error message on the return value of a stubbed function, that mocks the return of an Observable (using rxjs-marbles).

The issue I'm having is that the error message seems to state that a property of an object does not exist on the return type.

From the unit test file

it('', marbles((m) => {
     stub(ambulatoryListDataManager, 'combinedMultipleSearchStatuses').returns(
        m.cold('a', [
          {
            searchStatus: SearchStatus.active, // SearchStatus is an enum type
            flags: { loaded: true, loading: false },
            list: recordList,
          },
          {...},
        ]),
      );
});

I'm getting the following type error:

Type '{ searchStatus: SearchStatus.active; flags: { loaded: true; loading: false; }; list: IRecord[]; }' is not assignable to type '{ searchStatus: SearchStatus; flags: ListFlagsSelection; list: IRecord[]; }[]'.
  Object literal may only specify known properties, and 'searchStatus' does not exist in type '{ searchStatus: SearchStatus; flags: ListFlagsSelection; list: IRecord[]; }[]'

context.d.ts(11, 9): The expected type comes from this index signature

As you can see, the very property searchStatus, that it claims does not exist on the Object literal, is right there in the type definition shown in the error message. It does not seem to complain about the other properties.

Please note that SearchStatus is an enum type.

Everything seem completely fine to me, so why am I getting this error?

This is an inferred typing, so I though maybe it would help to make the return of the function explicit, but it does not help, I still have the same issue.

For further context, if needed, here is the function, and the function itself relies on. The first function is the one that provides the details that typescript uses to infer the expected return.

public combinedSearchStatuses(searchStatus: SearchStatus) {
    return combineLatest(...).pipe(
      map(([flags, list]) => ({ searchStatus, flags, list })),
    );
  }

  public combinedMultipleSearchStatuses(searchStatuses: SearchStatus[]) {
      return combineLatest(searchStatuses.map(
        (searchStatus) => this.combinedSearchStatuses(searchStatus)),
      ).pipe(distinctUntilChanged((a, b) => {...})

Einar Ólafsson
  • 3,036
  • 1
  • 19
  • 24

2 Answers2

1

The error is slightly misleading and hard to spot, it is complaining that searchStatus doesn't exist on the array type which is true.

This line specifically,

Type '{ searchStatus: SearchStatus.active; flags: { loaded: true; loading: false; }; list: IRecord[]; }' is not assignable to type '{ searchStatus: SearchStatus; flags: ListFlagsSelection; list: IRecord[]; }[]'.

Here is a TS playground to further show why

I believe you need to return an array of observables rather than one observable with an array of objects.

Something like [m.cold('a', { ... }, m.cold('a', {...})]

  • I should perhaps have specified that `SearchStatus` is an enum, so it should work like this. Using only `SearchStatus` would give the same error. – Einar Ólafsson Dec 09 '21 at 21:01
  • I updated my answer, looks like we both were confused from the type error. – Antonio Gargaro Dec 09 '21 at 21:26
  • Thank you for your help Antonio, I just realized now that I overlook a critical step in my definition for defining the marble test observable. So you are kind of right, but what is requires is a bit different, I will add an answer to explain. – Einar Ólafsson Dec 09 '21 at 21:51
1

After Antonios answer about the need to return array of Observables, I realized that I had overlooked a step in the definition of the rxjs marble. I need to define the return step for a

Here is how it should look like:

 stub(ambulatoryListDataManager, 'combinedMultipleSearchStatuses').returns(
        m.cold('-a', {
          a: [
            {
              searchStatus: SearchStatus.active,
              flags: { loaded: true, loading: false },
              list: recordList,
            },
            {
              searchStatus: SearchStatus.active,
              flags: { loaded: true, loading: false },
              list: recordList,
            },
          ],

Since I forgot to define the object correctly, it was complaining that the return was not correctly defined

Einar Ólafsson
  • 3,036
  • 1
  • 19
  • 24