62 words
1 minute
A Practical Guide to TypeScript Generics
Why Generics?
Without generics, you’re stuck choosing between type safety and flexibility. Generics give you both.
// Without generics — loses type informationfunction first(arr: any[]): any { return arr[0];}
// With generics — type-safe and flexiblefunction first<T>(arr: T[]): T | undefined { return arr[0];}
const num = first([1, 2, 3]); // type: numberconst str = first(['a', 'b', 'c']); // type: stringGeneric Constraints
Use extends to restrict what types are accepted:
interface HasLength { length: number;}
function logLength<T extends HasLength>(item: T): T { console.log(item.length); return item;}
logLength("hello"); // ✅ string has .lengthlogLength([1, 2, 3]); // ✅ array has .lengthlogLength(42); // ❌ number has no .lengthGeneric Interfaces
interface ApiResponse<T> { data: T; status: number; message: string;}
interface User { id: number; name: string; email: string;}
// The response is strongly typedconst response: ApiResponse<User> = { data: { id: 1, name: 'LeviFREE', email: 'levi@example.com' }, status: 200, message: 'OK',};Generic Utility Types
TypeScript ships with powerful built-in generics:
interface User { id: number; name: string; email: string; password: string;}
type PublicUser = Omit<User, 'password'>;type UserUpdate = Partial<User>;type ReadonlyUser = Readonly<User>;type UserKeys = keyof User; // "id" | "name" | "email" | "password"Real-World Example: A Type-Safe Event Emitter
type EventMap = { login: { userId: string; timestamp: Date }; logout: { userId: string }; error: { code: number; message: string };};
class TypedEmitter<T extends Record<string, any>> { private listeners = new Map<keyof T, Set<Function>>();
on<K extends keyof T>(event: K, handler: (payload: T[K]) => void) { if (!this.listeners.has(event)) { this.listeners.set(event, new Set()); } this.listeners.get(event)!.add(handler); }
emit<K extends keyof T>(event: K, payload: T[K]) { this.listeners.get(event)?.forEach(fn => fn(payload)); }}
const emitter = new TypedEmitter<EventMap>();
emitter.on('login', ({ userId, timestamp }) => { // userId and timestamp are fully typed});
emitter.emit('error', { code: 404, message: 'Not found' }); // ✅emitter.emit('error', { wrong: true }); // ❌ Type errorGenerics are one of TypeScript’s most powerful features. Once they click, you’ll wonder how you ever wrote code without them.
Share
If this article helped you, please share it with others!
A Practical Guide to TypeScript Generics
https://blog.levifree.com/posts/typescript-generics-guide/ Some information may be outdated
Related Posts Smart
1
Regex Cheat Sheet for Developers
Programming A practical regex reference with real-world examples. Stop guessing and start understanding regular expressions.
2
Python Virtual Environments Explained
Programming Understanding Python virtual environments, venv, pip, and modern tools like uv and Poetry. Never pollute your system Python again.
3
SSH Key Management: A Complete Guide
Security Everything you need to know about SSH keys — generating, managing, and using them securely for server access and Git authentication.
4
Setting Up a Home Lab: A Beginner's Guide
Home Lab Build your own home lab for learning, self-hosting, and experimentation. From hardware choices to software stacks and network configuration.
5
Introduction to WebSockets: Real-Time Communication
Web Dev Learn how WebSockets enable real-time, bidirectional communication between client and server. Build a simple chat system from scratch.
Random Posts Random
1
Markdown Tips and Tricks for Technical Writing
Writing 2026-05-16
2
PostgreSQL: Essential Queries and Tips
Backend 2026-06-10
3
Regex Cheat Sheet for Developers
Programming 2026-05-24
4
Python Virtual Environments Explained
Programming 2026-06-19
5
Nginx Reverse Proxy: The Complete Setup Guide
DevOps 2026-06-13





