How can I specify the action type when creating an action with NgRx action creator?

Since switching to NgRx's new action creator pattern in a fresh application, I've realized that I miss having a clearly defined type for actions. This becomes especially evident when testing services, as I want to ensure that the correct action with the right properties is dispatched.

How can I maintain type safety in TypeScript while addressing this issue?

Here's an illustrative example:

// In the line below, what should '???' be replaced with?
spyOn(store, "dispatch").and.callFake((action: ???) => {
  expect(action.type).toBe(fetchProductStructureAction.type);
  // Without the correct type, TypeScript flags an error here
  expect(action.property).toBe(expectedProperty); // <--
})

Answer №1

You can insert an Action from the ngrx/store library here.

This method is guaranteed to work.

spyOn(store, 'dispatch').and.callFake((action: Action) => {
  expect(action).toEqual(jasmine.objectContaining({
    type: fetchProductStructureAction.type,
    property: expectedProperty,
  }));
});

If you wish to maintain the original type in the callback, then you must cast the method to any, which leads to scenarios involving ReturnType for creator functions.

spyOn(store, "dispatch" as any).and.callFake((action: MyActionCreatorFunction) => {
  expect(action.type).toBe(fetchProductStructureAction.type);
  expect(action.property).toBe(expectedProperty);
})

Answer №2

In the response provided by Luis Aceitune, you can see that this method works well:

ReturnType<typeof myActionCreator>

For example:

export const loadDataAction = createAction('[Example] Load Data', props<{ id: string }>());

type LoadDataAction = ReturnType<typeof loadDataAction>;

https://i.sstatic.net/8fSaP.png

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

Restrict and ignore associated field in typeorm

I need help in restricting the related data when querying using query builder. Here is the code I have for fetching employee orders: import { getRepository, Repository } from "typeorm"; public async findEmployeeQuery(id : number) { try { ...

What causes Angular2 to detect both reference changes and primitive changes even when the OnPush flag is enabled?

Take a look at this code snippet import {Component, OnInit, Input, OnChanges, DoCheck, ChangeDetectionStrategy} from 'angular2/core' @Component({ selector: 'child1', template: ` <div>reference change for entire object: { ...

Dynamically apply classes in Angular using ngClass

Help needed with setting a class dynamically. Any guidance is appreciated. Below is the class in my SCSS file: .form-validation.invalid { border: 2px solid red } In my ts file, there's a variable named isEmailValid. When this variable is set to ...

Update the useState function individually for every object within an array

After clicking the MultipleComponent button, all logs in the function return null. However, when clicked a second time, it returns the previous values. Is there a way to retrieve the current status in each log within the map function? Concerning the useEf ...

What is the best way to reload a React/TypeScript page after submitting a POST request?

I am working on a custom plugin for Backstage that interacts with Argo CD via API calls. To retrieve application information, I make a GET request to the following endpoint: https://argocd.acme.com/api/v1/applications/${app-name} If the synchronizati ...

Error in compiling caused by an absent property on JSX element

While working with material-ui, I came across a Slider element: <Slider ... sliderStyle={{}} ...> An error message popped up: error TS2339: Property 'sliderStyle' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttri ...

Tips for showcasing saved images in Spring Boot with Angular 4

I am currently utilizing Spring Boot in combination with Angular 4. The issue I am facing involves uploading an image to the project location. However, upon attempting to view the uploaded image, it does not display correctly and instead throws an error. H ...

Is there a way to determine the tally of users who have achieved a score greater than that of [userID]?

I have this SQL code that helps to determine the position of a specific entry based on its score compared to other entries. select (select count(*) from entries e2 where e1.score < e2.score) + 1 as pos from entries e1 where e1.ID = 36; Transla ...

Trouble with Vue3 Ref and Reactivity not displaying changes or updating

I'm seeking to grasp the concept of ref/reactivity in Vue3. Unfortunately, due to work constraints, we are unable to utilize any state management libraries. The objective is to manipulate the number of objects in an array and have the ability to edit ...

Tips for accurately defining the return type for querySelector(All) connections

I enjoy doing this particular task, ensuring the types are correct. const qs = document.querySelector.bind(document) as HTMLElementTagNameMap | null; const qsa = document.querySelectorAll.bind(document) as NodeListOf<any>; While hovering over query ...

Using Javascript, Typescript, and Angular 5 to access and view a file

Currently, I am utilizing Angular 5 for a project that involves the need to extract an AMP HTML file as plain text. The specific file is stored within a component and must be accessed solely from that component. My primary goal is to have the capability t ...

Exploring routing within a Higher Order Component in React Native

I am looking to implement a file existence check on every page of my app. The idea is that if a specific file exists, the user should be redirected to another page. One solution I have considered is using a Higher Order Component (HOC) for this purpose. A ...

How do I condense nested keys in TypeScript?

If I have two types defined in TypeScript: interface Foo { bar: string; } interface Baz { foo: Foo; } Is it possible to flatten the Baz type in TypeScript (e.g. type FlatBaz = Flatten<Baz>), so that the signature appears similar to this? inte ...

Puppeteer: Simulating WebSocket Connections

How can I simulate WebSocket communication in Puppeteer? I'm currently testing my web application without a real backend and have been able to mock Ajax calls using the on request handler. However, I now need to test how my application responds to Web ...

Guidance on Sending Slider Values to a React Form within a Component

I am currently developing a React application using Typescript. One of the features I implemented is a multi-step form, where each form page is its own component and fields are individual components as well. While I can successfully view data from Text Fie ...

What is the best way to create a generic function parameter for a single property of an object?

I am trying to refactor a generic function into accepting parameters as a single object function test<T>(a: string, b: T, c: number) Instead, I want the function to receive an object like this: function test(params: {a: string; b: T, c: number}) I ...

There appears to be no overload that aligns with this call using styled components (index.d.ts(2187, 9))

Trying to create an Input component using styled components that accepts props but encountering an error when using the onChange prop - No overload matches this call. It seems like there might be an issue with my types, but even after extensive research, I ...

Can someone tell me how to implement the spy function within an object in Angular using Jasmine?

Below is a method written in the service called CapacitorManager: backButtonHandler() { return () => { const activeModalInstance = this.dataService.getItem(Constants.activeModalInstanceKey); const doesActiveModalExist = a ...

Consecutive API requests within React context

When I'm developing locally, I encounter the error message Error: Rendered more hooks than during the previous render. in my application when refreshing the page. I suspect this is happening because I am making two calls within my provider. The first ...

Using Express middleware in a TypeScript Express application

I'm currently converting the backend of an ExpressJS application to Typescript. While working on the auth.routes.ts file, I encountered an issue with the middleware (authMiddleware). It seems like there might be a typing error, as the same code in the ...