Skip to content

Actions aren't resolved with generic slice return types #689

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
huwshimi opened this issue Aug 12, 2020 · 6 comments
Closed

Actions aren't resolved with generic slice return types #689

huwshimi opened this issue Aug 12, 2020 · 6 comments

Comments

@huwshimi
Copy link

When adding a return type to a generic createSlice function the action types are no longer resolved.

Here is the example from the docs with the return type added:

export const createGenericSlice = <
  T,
  Reducers extends SliceCaseReducers<GenericState<T>>
>({
  name = "",
  initialState,
  reducers,
}: {
  name: string;
  initialState: GenericState<T>;
  reducers: ValidateSliceCaseReducers<GenericState<T>, Reducers>;
}): Slice<GenericState<T>, Reducers, string> => { // Return type added here
  return createSlice({
    name,
    initialState,
    reducers: {
      start(state) {
        state.status = "loading";
      },
      /**
       * If you want to write to values of the state that depend on the generic
       * (in this case: `state.data`, which is T), you might need to specify the
       * State type manually here, as it defaults to `Draft<GenericState<T>>`,
       * which can sometimes be problematic with yet-unresolved generics.
       * This is a general problem when working with immer's Draft type and generics.
       */
      success(state: GenericState<T>, action: PayloadAction<T>) {
        state.data = action.payload;
        state.status = "finished";
      },
      ...reducers,
    },
  });
};

const wrappedSlice = createGenericSlice({
  name: "test",
  initialState: { status: "loading" } as GenericState<string>,
  reducers: {
    magic(state) {
      state.status = "finished";
      state.data = "hocus pocus";
    },
  },
});

const actions = wrappedSlice.actions;

actions.magic(); // Works fine
actions.start(); // Not found
actions.success(); // Not found

The start and success actions are not resolved: Property 'success' does not exist on type 'CaseReducerActions<{ magic(state: { data?: string; status: "loading" | "finished" | "error"; }): void; }>'..

Removing the return type allows the actions to resolve.

Am I providing the wrong return type or do I have to resolve the actions in another way?

Here is a playground with this code and errors.

I noticed createSlice is being updated, so maybe this issue will be resolved in the PR: #637.

@markerikson
Copy link
Collaborator

Out of curiosity, why are you trying to specify a return type there in the first place?

@huwshimi
Copy link
Author

huwshimi commented Aug 12, 2020

@markerikson we have @typescript-eslint/explicit-module-boundary-types turned on in our project.

So when I add export to createGenericSlice it complains about Missing return type on function. (@typescript-eslint/explicit-module-boundary-types)

@markerikson
Copy link
Collaborator

Well, that's why. Turn off that lint rule :)

If it compiles and runs fine without explicitly declaring a return type, then you don't need it here.

Lint rules are supposed to help you. If a lint rule doesn't "spark joy", turn it off :)

@huwshimi
Copy link
Author

@markerikson hah, fair point. I might just do that :).

@phryneas
Copy link
Member

Yeah, have to agree very strongly with Mark there. RTK enables you to write a lot less TS code, but when you start specifying it's types manually, you're in for a very bad time. I'd also suggest turning that rule off.

@huwshimi
Copy link
Author

Thanks a lot @phryneas and @markerikson, I'll do without the rule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants