You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Why is typescript saying that the action payload is possibly undefined in the extraReducer in a slice? #766
I created a login thunk action creator with createAsyncThunk:
export const login = createAsyncThunk<
Tokens, // Return type of the payload creator
Credentials, // First argument to the payload creator
{
dispatch: AppDispatch;
state: RootState;
extra: undefined;
rejectValue: LoginError; // The type of the response I get from the server
}
>('auth/login', async (credentials: Credentials, thunkAPI) => {
try {
// I've shortened it for the sake of brevity. But if this is relevant, I've included the code I've used below
const response = await client.post<LoginResponse>('login', credentials);
const { accessToken, refreshToken } = response.data;
return { accessToken, refreshToken };
} catch (e) {
const error = e as AxiosError<LoginError>;
const response = error.response as AxiosResponse<LoginError>;
return thunkAPI.rejectWithValue(response.data);
}
});
Then in the authSlice I handle the lifecycle actions:
export const authSlice = createSlice({
name: 'auth',
initialState,
extraReducers: builder => {
builder.addCase(login.pending, (state, action) => {
state.status = 'pending';
});
builder.addCase(login.fulfilled, (state, action) => {
state.status = 'loggedIn';
});
builder.addCase(login.rejected, (state, action) => {
state.status = 'failed';
state.error = action.payload; // Here the typescript compiler says: "action.payload is possibly 'undefined'". The type of state.error is LoginError | null
});
}
});
Why is that? I passed the rejectValue: LoginError; as the generic parameter to createAsyncThunk. action.payload will never be undefined. As soon as the login.rejected case reducer is called, shouldn't typescript know that action.payload is certainly of type LoginError?
I would suggest reviewing the type of response.data in your catch {} clause. It's likely that's being defined as LoginError | undefined, or something along those lines.
That's not the issue here.
The thing is: While you know for sure that if there is a payload, it is of type LoginError, there are still two scenarios you can come to that rejected situation:
you reject it with rejectWithValue - in this case, payload is set.
an error is thrown - in this case, payload is not set. This might happen if you re-trow an error, or an error occurs in your catch block, or outside of it.
As we cannot know for sure if that situation can occur in your code, we have to assume it can - and so payload is optional.
Reacted by Camille Fenton, Shols232, Brandon Wie, Bojan Vreco, seungrokyoon-hits, Alec Mather, Olaide Emmanuel, Vishal Sherathiya, Ensiye Karimi, maeda and 3 more
Reacted by Kleinhummel, seungrokyoon-hits and Yakov Belikov
Reacted by Vasilis Green, seungrokyoon-hits and Yakov Belikov
That's not the issue here.
The thing is: While you know for sure that if there is a payload, it is of type LoginError, there are still two scenarios you can come to that rejected situation:
you reject it with rejectWithValue - in this case, payload is set.
an error is thrown - in this case, payload is not set. This might happen if you re-trow an error, or an error occurs in your catch block, or outside of it.
As we cannot know for sure if that situation can occur in your code, we have to assume it can - and so payload is optional.
Ahh, that makes sense. Thank you very much!
Reacted by Lenz Weber-Tronic, Daniel Einars, seungrokyoon-hits, Ensiye Karimi and Yakov Belikov
Activity
markerikson commentedon Oct 18, 2020
I would suggest reviewing the type of
response.datain yourcatch {}clause. It's likely that's being defined asLoginError | undefined, or something along those lines.phryneas commentedon Oct 18, 2020
That's not the issue here.
The thing is: While you know for sure that if there is a payload, it is of type
LoginError, there are still two scenarios you can come to thatrejectedsituation:rejectWithValue- in this case, payload is set.catchblock, or outside of it.As we cannot know for sure if that situation can occur in your code, we have to assume it can - and so
payloadis optional.Kleinhummel commentedon Oct 18, 2020
Ahh, that makes sense. Thank you very much!