type-localstorage
v1.0.2
Published
A simple and powerful **type-safe wrapper** around `localStorage` for TypeScript projects.
Readme
typed-localstorage
A simple and powerful type-safe wrapper around localStorage for TypeScript projects.
✅ What This Library Does
const testStorage = createTypedStorage<TestData>('test-storage', {
prefix: 'demo',
defaultValue: {
name: 'Default User',
count: 0,
lastUpdated: new Date().toISOString()
}
});This creates a typed localStorage interface with:
✅ Key Features
1. Type Safety
You define the shape of your data:
interface TestData {
name: string;
count: number;
lastUpdated: string;
}Now your get() and set() are fully typed. Avoid bugs by ensuring you only store valid data.
2. Prefixing
prefix: 'demo'Ensures all keys are stored as demo-test-storage, helping avoid naming collisions with other data.
3. Default Value
If there's no value in localStorage, a default is returned automatically.
defaultValue: { ... }4. Cross-Tab Syncing
testStorage.onChange((newValue) => { ... })Keeps all open tabs in sync when one tab updates the data — perfect for modern web apps.
5. Built-in Serialization
No need to manually JSON.stringify or JSON.parse. This library does it for you.
🧠 Why This Library Is Useful
| Feature | Benefit |
|------------------------|-------------------------------------------------------------------------|
| 🔐 Type-Safety | Prevents bugs, improves dev experience |
| 🏷️ Prefix Support | Avoids key collisions in shared environments |
| 🧱 Default Values | Guarantees get() always returns a valid value |
| 🔄 Cross-tab Sync | Enables real-time synchronization across multiple tabs |
| 🔁 Built-in Serialization | Clean code: handles parsing/stringifying for you |
🟢 Real-World Use Cases
- Persisting UI preferences (theme, layout, language)
- Saving form progress across sessions
- Tracking counters or stats
- Syncing state across multiple open tabs
- Building dashboards or SPAs with persistent state
🚀 Example Usage (React)
import React, { useEffect, useState } from 'react';
import { createTypedStorage } from 'type-localstorage';
interface TestData {
name: string;
count: number;
lastUpdated: string;
}
function App() {
const testStorage = createTypedStorage<TestData>('test-storage', {
prefix: 'demo',
defaultValue: {
name: 'Default User',
count: 0,
lastUpdated: new Date().toISOString()
}
});
const [data, setData] = useState<TestData>(testStorage.get()!);
useEffect(() => {
const unsubscribe = testStorage.onChange((newValue) => {
if (newValue) setData(newValue);
});
return () => unsubscribe();
}, []);
const handleIncrement = () => {
const newData = {
...data,
count: data.count + 1,
lastUpdated: new Date().toISOString()
};
testStorage.set(newData);
setData(newData);
};
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newData = {
...data,
name: e.target.value,
lastUpdated: new Date().toISOString()
};
testStorage.set(newData);
setData(newData);
};
return (
<div style={{ padding: '20px' }}>
<h1>Type-Safe LocalStorage Demo</h1>
<div style={{ marginBottom: '20px' }}>
<label>
Name:
<input
type="text"
value={data.name}
onChange={handleNameChange}
style={{ marginLeft: '10px' }}
/>
</label>
</div>
<div style={{ marginBottom: '20px' }}>
<button onClick={handleIncrement}>
Increment Count: {data.count}
</button>
</div>
<div>
<strong>Last Updated:</strong> {new Date(data.lastUpdated).toLocaleString()}
</div>
<div style={{ marginTop: '20px', color: 'gray' }}>
<small>Open this page in multiple tabs to test cross-tab synchronization!</small>
</div>
</div>
);
}
export default App;📦 Install
npm install type-localstorage🧪 Contribute
We welcome improvements, new features, and bug fixes. Open an issue or a pull request!
📝 License
MIT License
