John Smith
John Smith

Reputation: 4353

Get action types from Redux Toolkit's createSlice

I'm using createSlice together with useReducer.

I'd like the dispatch to be typed properly, that is React.Dispatch<ReducerActions>.

How do I extract action types from createSlice?

The following does not work, it resolves to AnyAction... which is understandable I'd say, as all actions pass through all reducers.

Dispatch<Parameters<typeof slice["reducer"]>[1]>

Upvotes: 7

Views: 6170

Answers (2)

Linda Paiste
Linda Paiste

Reputation: 42218

createSlice stores the action creators as a keyed object in the property actions. What we are looking for is the union of the return types of all action creators. We will use a mapped type to get this.

type SliceActions<T> = {
    [K in keyof T]: T[K] extends (...args: any[]) => infer A ? A : never;
}[keyof T]

type ActionTypes = SliceActions<typeof slice.actions>

I used the counter example from the doc in this Playground Link and the value of ActionTypes evaluated to:

type ActionTypes = {
    payload: undefined;
    type: "counter/increment";
} | {
    payload: undefined;
    type: "counter/decrement";
} | {
    payload: number;
    type: "counter/incrementByAmount";
}

When I first wrote this answer (October 2020) the action types were inferred as type: string rather than specific string literals. With the latest versions of Redux Toolkit and TypeScript (as of March 2023) you actually get the exact types!

Upvotes: 7

hadnet
hadnet

Reputation: 31

Based on Linda type, There is another way for better typing:

const storeSlice = createSlice({
  //...
  reducers: {
    fetchData: (state, action: PayloadAction<string>) => {
      //...
    onFetchFailed: (state, action: PayloadAction<string>) => {
      //...
    },
  },
});
type SliceActions<T> = {
  [K in keyof T]: {type: K; payload: T[K] extends (...args: infer P) => void ? P[0] : never};
}[keyof T];

/* 
ActionTypes = {
    type: "fetchData";
    payload: string;
} | {
    type: "onFetchFailed";
    payload: string;
}
*/
type ActionTypes = SliceActions<typeof storeSlice.actions>;

Upvotes: 3

Related Questions