Software Development

Say Goodbye To Local Storage

A type-safe collection of functions to make local storage better

Say Goodbye To Local Storage
This image has been generated by AI.

Local storage by default is pretty hard to maintain.

Imagine having hundreds of keys with values of many different types. How do you handle this?

In this article, I will present snippets of typesafe local storage functions and explanations on how to use them correctly.

So let's dive right in!

The FormLocalStorage Class

This is a custom class designed using TypeScript and leverages the Browser Local Storage API.

The idea behind this class is to save, clear, and store data into local storage in a typesafe manner, no matter how many keys and data types you're working with.

import { debounce } from "lodash";

// Define the type-safe schema for the form data and the keys
interface StorageSchema {
  "form-data": { email: string; password: string };
  "user-preferences": { theme: "light" | "dark"; language: string };
}

type StorageKey = keyof StorageSchema;

export class FormLocalStorage {
  /**
   * Saves the form data to local storage
   * @param key - The key to save the form data to
   * @param formData - The form data to save
   */
  public static saveFormData<K extends StorageKey>(
    key: K,
    formData: StorageSchema[K]
  ): void {
    try {
      localStorage.setItem(key, JSON.stringify(formData));
    } catch (error) {
      console.error("Error saving form data", error);
    }
  }

  /**
   * Debounces the save form data function
   * @param timeout - The timeout in milliseconds
   * @param key - The key to save the form data to
   * @param formData - The form data to save
   */
  public static debouncedSaveFormData<K extends StorageKey>({
    timeout = 350,
    key,
    formData,
  }: {
    timeout?: number;
    key: K;
    formData: StorageSchema[K];
  }): () => void {
    return debounce(() => {
      FormLocalStorage.saveFormData(key, formData);
    }, timeout);
  }

  /**
   * Gets the form data from local storage
   * @param key - The key to get the form data from
   * @returns The form data or null if it doesn't exist
   */
  public static getFormData<K extends StorageKey>(
    key: K
  ): StorageSchema[K] | null {
    if (typeof window === "undefined") {
      return null;
    }

    const item = localStorage.getItem(key);
    if (!item) {
      return null;
    }

    try {
      return JSON.parse(item) as StorageSchema[K];
    } catch (error) {
      console.error("Error parsing form data", error);
      return null;
    }
  }

  public static clearFormData<K extends StorageKey>(key: K): void {
    try {
      localStorage.removeItem(key);
    } catch (error) {
      console.error("Error clearing form data", error);
    }
  }
}

There are four key functions shown:

  • saveFormData
  • debouncedSaveFormData
  • getFormData
  • clearFormData

You can always add more functions as you see fit.

Usage

// This will save the formData to local storage after 1000ms:
FormLocalStorage.debouncedSaveFormData({
  timeout: 1000,
  key: "form-data",
  formData: { email: "test@test.com", password: "123456" },
})();

// This gets the form data for a type-safe key and logs it
const formData = FormLocalStorage.getFormData("form-data");
console.log(formData);

// This clears the form data for a type-safe key
FormLocalStorage.clearFormData("form-data");

Conclusion

That's it!

I've kept this a short article because I only wanted to share the code snippet as a whole so you can use these functions right away.

Let me know if you enjoyed it, and I will make more articles like this in the future.

1