npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

make-typed-storage

v0.0.1

Published

Type-safe Web Storage for TypeScript. Schema-agnostic via Standard Schema.

Readme

make-typed-storage

Type-safe Web Storage for TypeScript. Validate with any schema library, get full autocomplete and type errors at compile time.

Features

🛡️ Schema-validated reads and writes — catch invalid data before it corrupts your storage.

🔮 Fully typed accessors — autocomplete on keys, type errors on wrong values, zero manual annotations.

🔌 Works with any Standard Schema library — Zod, Valibot, ArkType, and more.

🗄️ Works with localStorage, sessionStorage, or any custom StorageLike backend.

🎯 Structured error handling — StorageValidationError with the key that failed and all issues.

🪶 Zero runtime dependencies.

Install

npm install make-typed-storage

The problem

localStorage.setItem("prefs", JSON.stringify({ theme: "dark", lang: "en" }));

const raw = localStorage.getItem("prefs");
const prefs = raw ? JSON.parse(raw) : null;
//    ^? any — no type safety, no autocomplete

prefs.thmee;
// No error — typo in key, silently returns undefined

localStorage.setItem("prefs", JSON.stringify({ theme: 42 }));
// No error — wrong type, corrupted data

The solution

import { makeTypedStorage } from "make-typed-storage";
import { z } from "zod";

const prefs = makeTypedStorage(
  "prefs",
  z.object({ theme: z.enum(["light", "dark"]), lang: z.string() }),
  localStorage,
);

prefs.get("theme");
//        ^? "light" | "dark" — correct type, full autocomplete

prefs.get("thmee");
//        ~~~~~~ — Type error: "thmee" is not a valid key

prefs.setAll({ theme: 42, lang: "en" });
//                    ~~ — Throws StorageValidationError

Usage

Reading from storage

const theme = prefs.get("theme");
//    ^? "light" | "dark" | undefined

const all = prefs.getAll();
//    ^? { theme: "light" | "dark"; lang: string } | undefined

get reads without validation (fast path). getAll validates and returns undefined if the stored data is invalid.

Validated reads with strictGet

const theme = prefs.strictGet("theme");
//    ^? "light" | "dark"

strictGet validates the entire stored object before returning the value. Throws StorageValidationError if the data is invalid.

Writing to storage

prefs.set("theme", "dark");

prefs.setAll({ theme: "dark", lang: "en" });

set writes a single key without validation — useful for building up state incrementally. setAll validates the entire object before writing.

Partial updates with merge

prefs.setAll({ theme: "dark", lang: "en" });
prefs.merge({ lang: "pt" });
// Storage now contains: { theme: "dark", lang: "pt" }

merge reads existing data, shallow-merges the new partial, validates the result, and writes it back.

Clearing storage

prefs.clear();
prefs.isSet; // false

Using a custom storage backend

makeTypedStorage works with any object implementing StorageLike:

import { makeTypedStorage } from "make-typed-storage";

const storage: StorageLike = {
  getItem: (key) => cookies.get(key) ?? null,
  setItem: (key, value) => cookies.set(key, value),
  removeItem: (key) => cookies.delete(key),
};

const prefs = makeTypedStorage("prefs", schema, storage);

Convenience functions

For the two most common backends:

import { makeLocalStorage, makeSessionStorage } from "make-typed-storage";

const prefs = makeLocalStorage("prefs", schema);
const session = makeSessionStorage("session", schema);

Error handling

Validating methods throw StorageValidationError on failure, which includes the storage key and structured issues:

import { StorageValidationError } from "make-typed-storage";

try {
  prefs.strictGet("theme");
} catch (error) {
  if (error instanceof StorageValidationError) {
    console.log(error.storageKey); // "prefs"
    console.log(error.issues); // [{ message: "Expected string, received number" }]
  }
}

Error messages are descriptive:

Storage "prefs" validation failed:
  - Expected string, received number

Schema libraries

make-typed-storage works with any library that implements the Standard Schema spec.

Zod

import { z } from "zod";

const prefs = makeTypedStorage(
  "prefs",
  z.object({ theme: z.enum(["light", "dark"]), lang: z.string() }),
  localStorage,
);

Valibot

import * as v from "valibot";

const prefs = makeTypedStorage(
  "prefs",
  v.object({ theme: v.picklist(["light", "dark"]), lang: v.string() }),
  localStorage,
);

ArkType

import { type } from "arktype";

const prefs = makeTypedStorage(
  "prefs",
  type({ theme: "'light' | 'dark'", lang: "string" }),
  localStorage,
);

API

makeTypedStorage(storageKey, schema, storage)

Create a type-safe storage wrapper.

| Parameter | Type | Description | | ------------ | ------------------------------ | ---------------------------------------------------- | | storageKey | string | The key used in the storage backend | | schema | StandardSchemaV1<unknown, T> | Any Standard Schema compatible schema | | storage | StorageLike | Storage backend (localStorage, sessionStorage, etc.) |

Returns a TypedStorage<T> instance.

makeLocalStorage(storageKey, schema)

Convenience wrapper that uses globalThis.localStorage.

makeSessionStorage(storageKey, schema)

Convenience wrapper that uses globalThis.sessionStorage.

TypedStorage<T>

| Method | Returns | Validates | Throws on failure | | ----------------- | ------------------- | --------- | ------------------------ | | get(key) | T[K] \| undefined | No | — | | strictGet(key) | T[K] | Yes | StorageValidationError | | set(key, value) | void | No | — | | setAll(data) | void | Yes | StorageValidationError | | getAll() | T \| undefined | Yes | — (returns undefined) | | merge(data) | void | Yes | StorageValidationError | | clear() | void | No | — | | isSet | boolean | No | — | | toJSON() | T \| undefined | Yes | — (returns undefined) |

StorageValidationError

| Property | Type | Description | | ------------ | --------------------------------------- | --------------------------- | | storageKey | string | The storage key that failed | | issues | ReadonlyArray<StandardSchemaV1.Issue> | Validation issues | | message | string | Formatted error message |

StorageLike

interface StorageLike {
  getItem(key: string): string | null;
  setItem(key: string, value: string): void;
  removeItem(key: string): void;
}

Errors

  • Throws StorageValidationError when data fails schema validation
  • Throws TypeError if an async schema is passed (storage operations are synchronous)