# Role
You are a Svelte Store Expert who designs reactive store architectures with TypeScript types, derived stores, custom stores, and proper subscription management.
# Task
Create a comprehensive Svelte store system with writable stores, derived stores, custom stores, and TypeScript types for your application's state management.
# Instructions
**Store Requirements:**
**State Needs:**
```typescript
[DESCRIBE_STATE_STRUCTURE]
Examples:
- User authentication
- Shopping cart
- Form state
- UI state (modals, sidebars)
- Real-time data
- Cached API responses
```
**Store Type:**
- Simple writable: [YES_NO]
- Derived computations: [YES_NO_WHAT]
- Custom store logic: [YES_NO_WHAT]
- Persistence: [LOCALSTORAGE_SESSIONSTORAGE_NONE]
**TypeScript:**
- Use TypeScript: [YES_NO]
- Strict types: [YES_NO]
Based on this information:
1. **Basic Store Types:**
```typescript
import { writable, readable, derived } from 'svelte/store';
// Writable store
export const count = writable(0);
// Readable store (read-only)
export const time = readable(new Date(), (set) => {
const interval = setInterval(() => {
set(new Date());
}, 1000);
return () => clearInterval(interval);
});
// Derived store (computed from other stores)
export const doubled = derived(count, ($count) => $count * 2);
```
2. **TypeScript Store Definitions:**
```typescript
import { writable, derived, type Writable, type Readable } from 'svelte/store';
// Type-safe writable store
interface User {
id: string;
name: string;
email: string;
}
export const user: Writable<User | null> = writable(null);
// Type-safe derived store
export const userName: Readable<string> = derived(user, ($user) => $user?.name ?? 'Guest');
// Multiple store derivation
export const fullName: Readable<string> = derived(
[firstName, lastName],
([$firstName, $lastName]) => `${$firstName} ${$lastName}`
);
```
3. **Custom Store Pattern:**
```typescript
import { writable } from 'svelte/store';
function createCounter() {
const { subscribe, set, update } = writable(0);
return {
subscribe,
increment: () => update(n => n + 1),
decrement: () => update(n => n - 1),
reset: () => set(0)
};
}
export const counter = createCounter();
// Usage in component
<script>
import { counter } from './stores';
</script>
<p>Count: {$counter}</p>
<button on:click={counter.increment}>+</button>
<button on:click={counter.decrement}>-</button>
<button on:click={counter.reset}>Reset</button>
```
4. **Advanced Custom Store:**
```typescript
import { writable, derived, get } from 'svelte/store';
interface Todo {
id: string;
text: string;
completed: boolean;
}
function createTodoStore() {
const { subscribe, set, update } = writable<Todo[]>([]);
return {
subscribe,
add: (text: string) => {
const todo: Todo = {
id: crypto.randomUUID(),
text,
completed: false
};
update((todos) => [...todos, todo]);
},
toggle: (id: string) => {
update((todos) =>
todos.map((todo) => (todo.id === id ? { ...todo, completed: !todo.completed } : todo))
);
},
remove: (id: string) => {
update((todos) => todos.filter((todo) => todo.id !== id));
},
clear: () => set([]),
// Async method
load: async () => {
const response = await fetch('/api/todos');
const todos = await response.json();
set(todos);
}
};
}
export const todos = createTodoStore();
// Derived stores
export const completedTodos = derived(todos, ($todos) => $todos.filter((t) => t.completed));
export const activeTodos = derived(todos, ($todos) => $todos.filter((t) => !t.completed));
export const todoCount = derived(todos, ($todos) => $todos.length);
```
5. **Store with Persistence:**
```typescript
import { writable } from 'svelte/store';
function createPersistedStore<T>(key: string, initialValue: T) {
// Get from localStorage
const storedValue = localStorage.getItem(key);
const data = storedValue ? JSON.parse(storedValue) : initialValue;
const store = writable<T>(data);
// Subscribe to changes and persist
store.subscribe((value) => {
localStorage.setItem(key, JSON.stringify(value));
});
return store;
}
export const preferences = createPersistedStore('preferences', {
theme: 'light',
language: 'en'
});
```
6. **Async Store Pattern:**
```typescript
import { writable, derived } from 'svelte/store';
interface AsyncState<T> {
data: T | null;
loading: boolean;
error: Error | null;
}
function createAsyncStore<T>(fetchFn: () => Promise<T>) {
const store = writable<AsyncState<T>>({
data: null,
loading: false,
error: null
});
async function load() {
store.update(state => ({ ...state, loading: true, error: null }));
try {
const data = await fetchFn();
store.set({ data, loading: false, error: null });
} catch (error) {
store.set({ data: null, loading: false, error: error as Error });
}
}
return {
subscribe: store.subscribe,
load,
reset: () => store.set({ data: null, loading: false, error: null })
};
}
// Usage
export const users = createAsyncStore(async () => {
const response = await fetch('/api/users');
return response.json();
});
// In component
<script>
import { users } from './stores';
import { onMount } from 'svelte';
onMount(() => {
users.load();
});
</script>
{#if $users.loading}
<p>Loading...</p>
{:else if $users.error}
<p>Error: {$users.error.message}</p>
{:else if $users.data}
<ul>
{#each $users.data as user}
<li>{user.name}</li>
{/each}
</ul>
{/if}
```
7. **Store Composition:**
```typescript
import { writable, derived } from 'svelte/store';
// Base stores
export const cart = writable<CartItem[]>([]);
export const products = writable<Product[]>([]);
// Composed derived stores
export const cartTotal = derived(cart, ($cart) =>
$cart.reduce((sum, item) => sum + item.price * item.quantity, 0)
);
export const cartCount = derived(cart, ($cart) =>
$cart.reduce((sum, item) => sum + item.quantity, 0)
);
export const cartWithDetails = derived([cart, products], ([$cart, $products]) => {
return $cart.map((cartItem) => ({
...cartItem,
product: $products.find((p) => p.id === cartItem.productId)
}));
});
```
8. **Store Subscription Management:**
```typescript
import { onDestroy } from 'svelte';
import { myStore } from './stores';
// Auto-unsubscribe with $
<script>
import { myStore } from './stores';
// $myStore automatically subscribes and unsubscribes
</script>
<p>{$myStore}</p>
// Manual subscription (when you need control)
<script>
import { onDestroy } from 'svelte';
import { myStore } from './stores';
let value;
const unsubscribe = myStore.subscribe(v => {
value = v;
});
onDestroy(unsubscribe);
</script>
// Multiple subscriptions
<script>
import { onDestroy } from 'svelte';
import { store1, store2, store3 } from './stores';
const unsubscribers = [
store1.subscribe(v => {}),
store2.subscribe(v => {}),
store3.subscribe(v => {})
];
onDestroy(() => {
unsubscribers.forEach(unsub => unsub());
});
</script>
```
9. **Store with Validation:**
```typescript
import { writable } from 'svelte/store';
function createValidatedStore<T>(initialValue: T, validator: (value: T) => boolean) {
const { subscribe, set, update } = writable<T>(initialValue);
return {
subscribe,
set: (value: T) => {
if (validator(value)) {
set(value);
} else {
console.error('Invalid value:', value);
}
},
update: (fn: (value: T) => T) => {
update((currentValue) => {
const newValue = fn(currentValue);
if (validator(newValue)) {
return newValue;
}
console.error('Invalid value:', newValue);
return currentValue;
});
}
};
}
// Usage
export const age = createValidatedStore(0, (value) => value >= 0 && value <= 120);
```
10. **Store Testing:**
```typescript
import { get } from 'svelte/store';
import { counter } from './stores';
describe('counter store', () => {
beforeEach(() => {
counter.reset();
});
it('starts at 0', () => {
expect(get(counter)).toBe(0);
});
it('increments', () => {
counter.increment();
expect(get(counter)).toBe(1);
});
it('decrements', () => {
counter.decrement();
expect(get(counter)).toBe(-1);
});
it('resets', () => {
counter.increment();
counter.increment();
counter.reset();
expect(get(counter)).toBe(0);
});
it('notifies subscribers', () => {
const values: number[] = [];
const unsubscribe = counter.subscribe((value) => {
values.push(value);
});
counter.increment();
counter.increment();
expect(values).toEqual([0, 1, 2]);
unsubscribe();
});
});
```
11. **Complete Store System:**
Provide comprehensive store architecture with:
- TypeScript type definitions
- Writable stores
- Derived stores
- Custom store methods
- Persistence layer
- Async handling
- Validation
- Testing examples
- Usage documentation
Deliver a production-ready Svelte store system with proper TypeScript types, reactive computations, custom methods, and comprehensive examples.