Enabling strict functions type causes an error when using destructuring with combineLatest

After enabling the strictFunctionTypes check in my Angular 11.1.1 project, I encountered an issue with a function that uses RxJs combineLatest. The type passed to the subscription remains an array and is not automatically destructured into individual variables, causing an error.

Disabling strictFunctionTypes resolves the issue, but I'm looking for a way to refactor the code to adhere to the strictFunctionTypes rule.

combineLatest([
      this.user$.pipe(startWith(null as User)),
      this.order$.pipe(startWith(null as Order)),
      this.invoice$.pipe(startWith([] as Faktura[])),
      this.document$.pipe(startWith([] as Document[]))
    ]).pipe(
      tap(([ order, user, invoices, docs ]: [ Partner, User, Faktura[], Document[]]) => {
        this.ordersCache$.next(order);
        this.usersCache$.next(user);
        this.invoicesCache$.next(invoices);
        this.docsCache$.next(docs);
      }),
      catchError(() => of([
        this.ordersCache$.value,
        this.usersCache$.value,
        this.invoicesCache$.value,
        this.docsCache$.value,
      ])),
      takeUntil(this.destroy$)
    ).subscribe({
      // The type is (Order | User | Faktura[] | Document[])[] and does not
      // automatically destructure it into the single entities.
      // This make the strictFunctionTypes rule fail as it does
      // not match the given parameter

      next: ([ order, user, invoices, docs ]: [
        Order,
        User,
        Faktura[],
        Document[]
      ]) => {
        // ...
     },
      error: (err) => {
        throw new Error(err);
      }
    });

UPDATE

Upon trying kvetis suggestion of using tap instead of map and omitting the return, the error still persists:

https://i.sstatic.net/h3p9o.png

The ongoing issue seems to be related to the catchError block because when removed, the exception no longer occurs.

Answer №1

There is an issue with the

return [ partner, user, invoices ];
statement as it creates a different type than what is expected. You must specify to typescript that the array should be treated as a tuple.

return [ partner, user, invoices ] as [ Partner, User, Invoice[]];

In the given example, using map is unnecessary since it is only being used for side effects. By using tap, you can avoid any issues.

combineLatest([
      this.user$.pipe(startWith(null as User)),
      this.order$.pipe(startWith(null as Order)),
      this.invoice$.pipe(startWith([] as Invoice[]))
    ]).pipe(
      tap(([ order, user, invoices ]: [ Partner, User, Invoice[]]) => {
        this.ordersCache$.next(order);
        this.usersCache$.next(user);
        this.invoicesCache$.next(invoices);
      }),
      takeUntil(this.destroy$)
    ).subscribe({

      next: ([ order, user, invoices ]: [
        Order,
        User,
        Invoice[]
      ]) => {
        // ...
     },
      error: (err) => {
        throw new Error(err);
      }
    });

UPDATE: CatchError Issue

To address the problem, explicitness is required. The same solution for the mapping function applies here - specifying to treat items as a tuple instead of an array. It follows a similar approach to the initial fix proposed.

      catchError(() => of([
        this.ordersCache$.value,
        this.usersCache$.value,
        this.invoicesCache$.value,
        this.docsCache$.value,
      ]) as [Order, User, Faktura[], Document[]]),

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Would it be possible to use the Stripe customer portal to facilitate subscription upgrades or downgrades that take effect at the end of the current billing cycle?

I am struggling to figure out how to manage subscription upgrades and downgrades on the user interface side so that they start at the end of the current billing cycle. The only Stripe-hosted page for handling subscription changes is the customer billing p ...

Typescript's default generic datatypes

I am currently working with a protractor list page object. By default, this object returns instances of ElementFinder, but there is a way to customize it to return instances of ComplexType like the following: class ComplexType { foo = 'foo'; ...

What is the reason behind providing self-references in Typescript interfaces?

type SomeGeneric<T> = { x: T; } type TTest = SomeGeneric<TTest> & { a: string; }; // The type alias 'TTest' creates a circular reference. interface ITest extends SomeGeneric<ITest> { // This is acceptable a: string ...

"Troubleshooting: IONIC 4 ion-menu not visible when ion-menu-button is clicked

I am attempting to implement a side menu using ion-menu within my Angular 6 application. However, upon adding the toggle button for the menu and clicking it, nothing seems to occur. There are no error messages or any visible changes on the screen. // wher ...

Struggles with deducing argument types in Typescript

I'm struggling to comprehend an inference error. The ts linter highlights (event: E) within useCallback with the following message. When I cast the callback of useCallback with as T, the linter message disappears. Is there a way to avoid this workarou ...

What is the best way to find a partial string match within an array of objects when using Jest?

I am currently utilizing the following versions: Node.js: 9.8.0 Jest: 22.4.2 A function called myFunction is returning an array structured like this: [ ... { id: 00000000, path: "www.someUrl.com/some/path/to" } ... ] I ...

How can we implement ngxs async observable interpolation in a component.ts file instead of the HTML?

When working on my Angular app's HTML, I successfully displayed the "title" from a variable using the following code: The following code worked fine in my component.html file: <input matInput value="{{ (app$ | async).myTitle.match('title: &a ...

The input field or help text fails to change to a red color when the field contains invalid information

Previously, I developed an Angular 2/4 application using Bootstrap 3 and Reactive Forms for field validation. In this setup, when there was an error in input fields, the border of the field turned red and an error message would display below the field in r ...

Developing Angular dynamic components recursively can enhance the flexibility and inter

My goal is to construct a flexible component based on a Config. This component will parse the config recursively and generate the necessary components. However, an issue arises where the ngAfterViewInit() method is only being called twice. @Component({ ...

Angular - Slow rendering of views causing performance degradation

I am currently developing a cutting-edge Ionic Angular App. One of the pages in my app displays a spinner while waiting for data to be fetched from an API REST service. However, I'm facing an issue where even after the spinner disappears, it takes ar ...

Tips for distinguishing a mapped type using Pick from the original type when every property is optional

I am working with a custom type called ColumnSetting, which is a subset of another type called Column. The original Column type has most properties listed as optional: type ColumnSetting = Pick<Column, 'colId' | 'width' | 'sort ...

What processes occur behind the scenes when DownGit downloads specific files or folders from GitHub?

I was looking for a way to download specific files or folders from GitHub and discovered DownGit. However, I am curious about the inner workings of this tool. After reading the README.md on https://github.com/MinhasKamal/DownGit, I still couldn't ful ...

Encounter an error message stating "Request failed with status code 502 nginx in Next.js TypeScript."

After setting up Next.js typescript with Kubernetes NGINX Ingress, I encountered a problem where specific routes were returning a 502 error. For example, the route /test works fine, but /login does not. I'm unsure whether the issue lies with Kubernete ...

Unable to simultaneously execute TypeScript and nodemon

Currently, I am in the process of developing a RESTful API using Node.js, Express, and TypeScript. To facilitate this, I have already installed all the necessary dependencies, including nodemon. In my TypeScript configuration file, I made a modification to ...

Solving Unit Testing Issues with Karma-Jasmine for Angular's .sort() Method

Here is a snippet of Angular code that I have written: this.selectedData.sort((a, b) => { if (query === 'poll' && (a[query] === null || b[query] === null)) { return a[query] === null ? 1 : -1; } else if (quer ...

Retrieve information from the local storage every second

I have developed a new application using Angular 8. Within this component, I have created a model where users can select an option. I wrote a function in the TypeScript file to store this information in local storage. Now, I need assistance with retrieving ...

The Windows platform is not recognizing the --port option when using ng serve

When running ng serve in Windows, it doesn't recognize the --port option. However, I found that it works if I use npm run ng serve --port portnumber and it always defaults to 4200: oml005@W7-2UA532159M MINGW64 /d/COT-TF/cot-web/cot-web (master) ng ...

What is the best way to create and manage multiple collapsible Material-UI nested lists populated from an array with individual state in React

In my SideMenu, I want each list item to be able to expand and collapse independently to show nested items. However, I am facing the issue of all list items expanding and collapsing at the same time. Here is what I've attempted: const authNavigation ...

How can I be certain that I am utilizing the most recent ts/js files in Angular2

Clearing the browser cache with compiler.clearCache() seems to only work for HTML templates. Even after updating the TypeScript of components, old JavaScript files are still being used by browsers. Currently, I have to manually clear the browser cache and ...

Angular 2 - Updating a specific value with a click

Using the code snippet below, an autocomplete feature based on Google Places API can be implemented. As characters are typed into the input fields, the code fetches and displays a list of place names. The goal is to have the selected 'place' repl ...