I'm doing an app where i use redux toolkit and localstorage to save the theme.
I have this slice :
import { createSlice } from "@reduxjs/toolkit";
const mode = !localStorage.getItem("theme")
? ""
: JSON.parse(localStorage.getItem("theme")); //the error is on this line
const initialState = {
mode: mode,
};
const ThemeSlice = createSlice({
name: "theme",
initialState,
reducers: {
toggleTheme: (state) => {
state.mode = state.mode === "light" ? "dark" : "light";
},
},
});
export const { toggleTheme } = ThemeSlice.actions;
export default ThemeSlice.reducer;
but its giving me an error : Argument of type 'string | null' is not assignable to parameter of type 'string'.
What can i do to remove this error?
localStorage.getItem("theme")
return type is string | null
, but JSON.parse
expects string
, so the type(s) do not match. Even though localStorage.getItem("theme")
is evaluated in the ternary condition, Typescript can't tell that localStorage.getItem("theme")
in the falsey branch will evaluate to the same value, all it has is the getItem
return type of string | null
.
You could use Nullish Coalescing and simply provide a proper string
type fallback value to convert null
to an empty string.
const mode = JSON.parse(localStorage.getItem("theme") ?? "");
Alternative could be to read and store the theme from localStorage
into a variable and use that in the ternary expression, this way the type system references the same value throughout the expression.
const theme = localStorage.getItem('theme');
const mode = theme ? JSON.parse(theme) : '';
Optionally, you could assert the value is non-null (!
)
const mode = localStorage.getItem("theme")
? JSON.parse(localStorage.getItem("theme")!) // <-- assert non-null
: "";
But this is only an "escape hatch" if you are 100% absolutely certain localStorage.getItem("theme")
won't ever return a null
value.
Between the three options I recommend either of the first two options that stay within the type system safely.