Skip to content
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

Cannot resolve type circular dependency #1126

Closed
atiupin opened this issue Jun 3, 2021 · 6 comments
Closed

Cannot resolve type circular dependency #1126

atiupin opened this issue Jun 3, 2021 · 6 comments

Comments

@atiupin
Copy link

atiupin commented Jun 3, 2021

I'm quite new to redux-toolkit and have no idea how to solve this kind of circular dependency (code is heavily cut):

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";

interface Organization {
  name: string;
}

const fetchSingleOrganization = createAsyncThunk<Organization, string, { state: RootState }>(
  "organizations/fetch-single",
  async (id, { getState }) => {
    // fetch code
  },
);

const organizationsSlice = createSlice({
  name: "organizations",
  initialState: null,
  reducers: {},
  extraReducers: (builder) =>
    builder.addCase(fetchSingleOrganization.fulfilled, () => {
      // upsert code
    }),
});

const store = configureStore({
  reducer: {
    organizations: organizationsSlice.reducer,
  },
});

type RootState = ReturnType<typeof store.getState>;

This results in a Type alias 'RootState' circularly references itself.ts (2456) error. I need a full state in a fetchSingleOrganization function, not just this slice. I can see the problem, but don't know how to fix it. It would probably resolved fine, if there was an option to add extraReducers afterwards, but I can't see one. What is a correct approach here?

@phryneas
Copy link
Member

phryneas commented Jun 3, 2021

Assuming that slice and store creation will end up in different files in the end, the best approach to breaking the circle is to explicitly type the reducer.

- export default slice.reducer
+ export default slice.reducer as Reducer<typeof initialState>

@atiupin
Copy link
Author

atiupin commented Jun 3, 2021

Oh, that did worked out, thank you.

@atiupin atiupin closed this as completed Jun 3, 2021
@markerikson
Copy link
Collaborator

Yeah, we really need to add this to the RTK and core TS usage guides.

@DevTGhosh
Copy link

DevTGhosh commented Aug 12, 2021

For people who are converting their existing slice from js to ts in addition to typing the reducer export also remember to change the extraReducers syntax from

extraReducers: {
  [apiThunk.fetching]: (state, action) {
    //Your logic
  }
}

to

extraReducers: builders => {
  builders.addCase(apiThunk.fetching, (state, action) {
     //Your logic
    }
  )
}

as mentioned here .

@IuriKintschev
Copy link

IuriKintschev commented Jan 16, 2022

Sorry I know it's closed but I really don't understand how to make it work

My organization goes like this

store package
    |
    │   ├── slice1 file
    │   ├── slice2 file
    ├── store file

In my store I am exporting the type of my slices

export type RootState = ReturnType<typeof store.getState>;

And in my slice it is exporting as suggested, but even so I don't get the types of my state in getState() and when I pass the typing directly I end up importing from the store file and it accuses me of the circle error

export const getSites = createAsyncThunk<SitesResponseProps, void, { state: RootState }>(
  "sites/getSitesFromApi",
  async (_, { getState }) => {
    const { authentication } = getState();
  }
);

> OR

export const getSites = createAsyncThunk<SitesResponseProps, void>(
  "sites/getSitesFromApi",
  async (_, { getState }) => {
    const { authentication } = getState() as RootState;
  }
);

// ...


export default siteSlice.reducer as Reducer<typeof initialState>;

erro: Type alias 'RootState' circularly references itself.

I also tried to create a d.ts file but I get other typing error like any defined

declare module "@reduxjs/toolkit" {
    type AsyncThunkConfig = {
        state?: unknown;
        dispatch?: Dispatch;
        extra?: unknown;
        rejectValue?: unknown;
        serializedErrorType?: unknown;
    };

    function createAsyncThunk<
        Returned,
        ThunkArg = void,
        ThunkApiConfig extends AsyncThunkConfig = { state: RootState } 
    >(
        typePrefix: string,
        payloadCreator: AsyncThunkPayloadCreator<
            Returned,
            ThunkArg,
            ThunkApiConfig
        >,
        options?: AsyncThunkOptions<ThunkArg, ThunkApiConfig>,
    ): AsyncThunk<Returned, ThunkArg, ThunkApiConfig>;
}

@phryneas
Copy link
Member

@IuriKintschev this is a closed thread - pretty much everything that can be said has been said. If this does not solve it for you please create a new thread and provide a full reproduction. From just reading your code without a full application context I can't see any problems here.

@reduxjs reduxjs locked as resolved and limited conversation to collaborators Jan 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants