Search code examples
typescriptunit-testingngrx

NgRx: how do I declare the explicit type of an action created by action creator?


After starting a new application and using NgRx's new action creator pattern, I have found myself missing having an explicit type for an action. For example when I'm testing a service, I would like to know that it dispatched the correct action with the correct properties.

How do I go about this while retaining type safety in TypeScript?

An example:

// What should the '???' in the following line be?
spyOn(store, "dispatch").and.callFake((action: ???) => {
  expect(action.type).toBe(fetchProductStructureAction.type);
  // TypeScript complains here if I don't add the correct type to action
  expect(action.property).toBe(expectedProperty); // <--
})

Solution

  • You can put there Action from ngrx/store.

    this one works for sure.

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

    if you want to keep the original type in the callback then you need to cast method to any, but then it brings to the case with ReturnType for creator functions.

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