Search code examples
javascriptreactjstypescriptecmascript-6ecmascript-2016

React Typescript useLocalStorage Hook


i wrote a custom hook to interact with the sessionStorage in React. Currently I don't like that I can just arbitrarily write any key-value pair in there. For testing and debugging purposes I would like to introduce a form of TypeSafety and I was thinking about maybe using a Union Type rather then the Generic.

I basically want to achieve two goals.

  1. check if the key is a valid key that is allowed to be put into the sessionStorage
  2. if the key is allowed make sure the type of the value is correct.

Does anyone have any idea how you would go about implementing these sort of checks in Typescript. Any help is appreciated.

export function useSessionStorage<T>(key: string, initialValue: T) {
  const [storedValue, setStoredValue] = useState<T>(() => {
    try {
      const item = window.sessionStorage.getItem(key);// Parse stored json or if none return initialValue
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.log(error);
      return initialValue;
    }
  });
  const setValue = (value: T | ((val: T) => T)) => {
    try {
      const valueToStore =
        value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  };
  return [storedValue, setValue] as const;
}

Solution

  • In case someone stumbles across this question, I ended up finding how this is implemented in Typescript. You can achieve the desired effect by the use of the typeof operator on the generic.

    basically you first define a interface or type:

    type Allowed = {
      item1: string
      item2: boolean
      item3: number
    }
    

    Then you can modify the function using the keyof operator

    function useSessionStorage<T extends keyof Allowed>(key: T, initialValue: Allowed[T]){
        {...}
    }
    

    the use of key of is better described here: https://www.typescriptlang.org/docs/handbook/advanced-types.html.

    Hope this helps other people that might be struggling with this.