Hello there!
I was following the api docs and the usage with typescript docs for the new feature createAsyncThunk and everything was working as expected until I defined the extraReducers in the createSlice.

As the error says, I can't use the auto-generated promise lifecycle action as a computed property name, so instead of using fetchSession.fulfilled and fetchSession.rejected I'm forced to use fetchSession.fulfilled.type and fetchSession.rejected.type.
As this doesn't seem like a typo in the docs (the same references are everywhere!), am I missing something?
My thunk looks like this:
export type Session = {
subscriber?: number;
name?: string;
key?: string;
};
export type AuthSliceState = {
token: string;
session: Session;
};
export const fetchSession = createAsyncThunk<
Session,
string,
{ state: RootState }
>('auth/fetchSession', async (apiSig, { getState }) => {
const { token } = getState().auth;
const session = await getSession(token, apiSig);
return session as Session;
});
Thank you very much for your help!
Yeah, there's a couple issues here.
In the actual JS code, the interpreter will take {[fetchSession.fulfilled]: someFunction]} and implicitly stringify it by calling fulfilled.toString(), which returns the action type string. However, TypeScript doesn't know that is possible - it just sees that you're passing an action creator instead of a string in that computed key, and raise an error.
As an initial workaround, you can do [fetchSession.fulfilled.type] for both createReducer and the createSlice/extraReducers field.
However, that doesn't tell the TS compiler what the actual TS type of the action creator is, so you'll have to hand-specify what the action type is in the reducer if you're using the object form of extraReducers.
That's why the Usage with TypeScript docs page suggests using the "builder callback" form of extraReducers instead:
const usersSlice = createSlice({
name: 'users',
initialState,
reducers: {
// fill in primary logic here
},
extraReducers: builder => {
builder.addCase(fetchUserById.pending, (state, action) => {
// both `state` and `action` are now correctly typed
// based on the slice state and the `pending` action creator
})
}
})
This avoids the stringification issue, and also correctly infers the type of action based on the action creator so you don't have to repeat yourself.
That should resolve things for you - if not, please let us know!
@markerikson Thank you very much for the quick response! All clear now 馃槃
Most helpful comment
Yeah, there's a couple issues here.
In the actual JS code, the interpreter will take
{[fetchSession.fulfilled]: someFunction]}and implicitly stringify it by callingfulfilled.toString(), which returns the action type string. However, TypeScript doesn't know that is possible - it just sees that you're passing an action creator instead of a string in that computed key, and raise an error.As an initial workaround, you can do
[fetchSession.fulfilled.type]for bothcreateReducerand thecreateSlice/extraReducersfield.However, that doesn't tell the TS compiler what the actual TS type of the action creator is, so you'll have to hand-specify what the action type is in the reducer if you're using the object form of
extraReducers.That's why the Usage with TypeScript docs page suggests using the "builder callback" form of
extraReducersinstead:This avoids the stringification issue, and also correctly infers the type of
actionbased on the action creator so you don't have to repeat yourself.That should resolve things for you - if not, please let us know!