Shailesh Vaishampayan
Shailesh Vaishampayan

Reputation: 1796

Meaning of NgRx createAction method's return type signature

I have been going through NgRx Doumentation for createAction method as in below link : Overloads for createAction method

I am not able to understand below in type signature of this method, specifically the return Type of createAction method : What is

() => TypedAction<T>

in this signature :

 ActionCreator<T, () => TypedAction<T>>

I don't see any reference to TypedAction? Does it mean any object of shape of specific Action type?

What I understand by T in above signature of return type is that it is generic type for ActionCreator function which will return Action of type T when called. But Not sure the other Type argument indicates except that it seems to be some function which is returning TypedAction of type T. Would like to know a real world example.

Upvotes: 5

Views: 2014

Answers (1)

Andrei Mihalciuc
Andrei Mihalciuc

Reputation: 2258

TypedAction is a generic interface which extends Action type by adding a readonly type property.

export declare interface TypedAction<T extends string> extends Action {
  readonly type: T;
}

ActionCreator<T, () => TypedAction<T>> - tell us that we have a factory which returns a TypedAction object () => ({ type: T})

Let's define an action creator:

export const logout = createAction('[Auth] Logout');

createAction function is defined in action_creator.ts.

export function createAction<T extends string>(
  type: T
): ActionCreator<T, () => TypedAction<T>>;

from the declaration we can tell that createAction will return a function which in turn returns an object with a type property of string in our case as <T extends string>

Let's dive into the actual implementation a bit. When you don't provide a payload for your action creator the following code is executed:

export function createAction<T extends string, C extends Creator>(
  type: T,
  config?: { _as: 'props' } | C
): Creator {
...
    case 'empty':
      return defineType(type, () => ({ type }));
...
}

And defineType is:

function defineType(type: string, creator: Creator): Creator {
  return Object.defineProperty(creator, 'type', {
    value: type,
    writable: false,
  });
}

defineType accepts a type ('[Auth] Logout') and a Creator - () => ({ type }). It returns back Creator but with a new property type. So calling logout.type and logout().type will return the same value - '[Auth] Logout'

Later on, in the reducer_creator.ts it allows us to extract ActionCreator type ("[Auth] Logout" in our case), associate it to the reducer function and execute it

UPDATE: As the answer to question became to big, I've decided to write a blog post How do NgRx Action Creators work

Upvotes: 5

Related Questions