reduxjs / redux-toolkit

The official, opinionated, batteries-included toolset for efficient Redux development
https://redux-toolkit.js.org
MIT License
10.76k stars 1.18k forks source link

createSlice causing a TS Compiler error: "This is likely not portable, a type annotation is necessary" #790

Closed Vassi closed 3 years ago

Vassi commented 4 years ago

Fairly new to TS, and I had this slice working before we decided to switch to TS and suddenly I found myself wrestling with several bears at once when it comes to some of the typings for createSlice and createAsyncThunk.

I thought I had everything sorted and then noticed one final compiler error on authSlice: image

I have to admit I have 0 clue what this is expecting of me.

type SliceState = {
  loginRequired: boolean,
  authenticated: boolean,
  authenticationToken: string | null,
  authenticationPending: boolean,
  authenticationError: boolean,
  authenticationErrorMessage: string | null,
  authenticationErrorDetail: string | null,
  profile: null
}

export const initialState : SliceState = {
  loginRequired: false,
  authenticated: false,
  authenticationToken: null,
  authenticationPending: false,
  authenticationError: false,
  authenticationErrorMessage: null,
  authenticationErrorDetail: null,
  profile: null
};

export const authSlice = createSlice({
  name: 'authentication',
  initialState: initialState as SliceState,
  reducers: {
    revokeAuthentication: (state) => {
      state.authenticated = false;
      state.loginRequired = false;
      state.authenticationToken = null;
    }
  },
  extraReducers: (builder) => {
    builder.addCase(requestToken.fulfilled, (state, { payload }) => {
      // more stuff
    });
    // a lot more cases
  }
});
Vassi commented 4 years ago

Ok, maybe not a red-alarm, this error only appears on VS Code for some reason (?) when I do npm start with create-react-app it seems to compile and work just fine.

Still, I'd really rather not see this at all, so any feedback would be helpful.

phryneas commented 4 years ago

If I had to guess this might be because you have multiple versions of immer installed in your repository, so the inferred type references node_modules/@reduxjs/toolkit/node_modules/immer/... instead of node_modules/immer/... and TS warns about that.

But that's really just a guess :/

lafritay commented 3 years ago

@Vassi @phryneas I'm seeing this as well. I think this may be similar to this issue:

https://github.com/reduxjs/redux-toolkit/issues/472

Fundamentally, immer is part of the reduxjs/tookit api correct? Given that, it seems like rtk should export the entire immer library. My guess is that this issue is happening because createSlice returns types like WritableDraft that are not included in the exports in src/index.ts

markerikson commented 3 years ago

As far as I know, "exporting the whole lib" isn't relevant here. TS should be able to follow Immer's types into what's included with Immer itself.

phryneas commented 3 years ago

@lafritay Most of the time that seems to be the case because you have multiple different versions of immer installed in your application and the types of these might be conflicting with each other. Can you check that?

lafritay commented 3 years ago

@markerikson @phryneas I double-checked my dependencies - I did have a direct dependency on immer but it's version string ^7.0.3 matched that of the 1.4.0 rtk dependency.

To confirm something odd wasn't happening here, I dropped my direct dependency on immer and moved my imports to pull from the immer located in the @redux/toolkit/node_modules directory. The build errors remained.

After debugging some more, I found the issue - or at least a workaround. I had been importing produce from immer and using that. When I instead moved to using createNextState (imported from rtk) instead of produce, the build errors went away.

It seems like the issue will come back if I need to use anything from the immer library that isn't exported by rtk. I'm currently unblocked but wouldn't be surprised if this issue happens again in the future (for me or someone else).

phryneas commented 3 years ago

@lafritay that doesn't mean that something else did not install another version of immer. React-scripts seem to cause that oftentimes for example.

Try a yarn why immer if you use yarn or npx npm-why immer if you use npm.

lafritay commented 3 years ago

I think I had a corrupted version of immer or rtk in my node_modules. I ran npx npm-why immer a number of times for it only to tell me that @reduxjs/toolkit didn't have a dependency on it:

image

And after removing my direct dependency on it to see if that was masking it somehow:

image

Blowing away my node_modules, the backing cache and redownloading packages causes the errors to go away.

I appreciate the help working through this.


Update: On digging into this more trying to recreate it, I found that it is a problem with npm-shrinkwrap.json. The left-side of the diff has the problem. The right side does not.

image

I'm not enough of an npm wizard to understand what makes that segment show up or go away though. The only other entry in that file related to immer is this:

image

hugotox commented 3 years ago

Had the same issue in a lerna repo, fixed it by adding immer to the resolutions section in package.json

colemars commented 3 years ago

@hugotox can you give some more detail please?

Ah, so you resolved immer to a single version at the root of your monorepo.

mpearson commented 1 year ago

FWIW, I had this problem with my project which uses Bazel and pnpm to build, so I didn't have much hope for resolving it. I confirmed I only had one version of immer installed, tried adding resolutions etc but had no luck. Finally, I tried directly importing immer in the file with createSlice() and that resolved it. So if nothing else works, consider simply doing

import 'immer';