npm create vite@latest --template vanilla-ts
Build a typed generic cache, repository interface, and event emitter.
1 // Typed in-memory cache 2 class TypedCache<K, V> { 3 private store = new Map<K, V>(); 4 set(key: K, value: V): void { this.store.set(key, value); } 5 get(key: K): V | undefined { return this.store.get(key); } 6 has(key: K): boolean { return this.store.has(key); } 7 clear(): void { this.store.clear(); } 8 } 9 10 // Generic repository interface 11 interface Repository<T extends { id: string }> { 12 findById(id: string): Promise<T | null>; 13 findAll(): Promise<T[]>; 14 save(entity: T): Promise<T>; 15 delete(id: string): Promise<boolean>; 16 } 17 18 // In-memory implementation for testing 19 class InMemoryRepository<T extends { id: string }> implements Repository<T> { 20 private items = new Map<string, T>(); 21 22 async findById(id: string): Promise<T | null> { 23 return this.items.get(id) ?? null; 24 } 25 async findAll(): Promise<T[]> { return Array.from(this.items.values()); } 26 async save(entity: T): Promise<T> { 27 this.items.set(entity.id, entity); 28 return entity; 29 } 30 async delete(id: string): Promise<boolean> { 31 return this.items.delete(id); 32 } 33 } 34 35 // Usage 36 interface User { id: string; name: string; email: string; } 37 const userRepo = new InMemoryRepository<User>(); 38 const cache = new TypedCache<string, User>(); 39 40 async function main() { 41 const user = await userRepo.save({ id: '1', name: 'Alice', email: 'alice@example.com' }); 42 cache.set(user.id, user); 43 console.log(await userRepo.findById('1')); // User 44 console.log(cache.get('1')); // User from cache 45 }
TypedCache<string, User> compiles; invalid key types rejected by TypeScript
Sign in to share your feedback and join the discussion.