Web Development TypeScript Subjective
Oct 04, 2025

How do you implement a type-safe event system with payload validation?

Detailed Explanation
Use discriminated unions for event types, mapped types for event-payload relationships, and conditional types for type-safe event handling. Basic Event System: type EventMap = { 'user:login': { userId: string; timestamp: Date }; 'user:logout': { userId: string }; 'post:created': { postId: string; authorId: string; title: string }; 'post:deleted': { postId: string }; }; type EventName = keyof EventMap; type EventPayload = EventMap[T]; class TypeSafeEventEmitter { private listeners: { [K in EventName]?: Array<(payload: EventPayload) => void>; } = {}; on( event: T, listener: (payload: EventPayload) => void ): void { if (!this.listeners[event]) { this.listeners[event] = []; } (this.listeners[event] as any[]).push(listener); } emit(event: T, payload: EventPayload): void { const eventListeners = this.listeners[event]; if (eventListeners) { eventListeners.forEach(listener => listener(payload)); } } } // Usage const emitter = new TypeSafeEventEmitter(); emitter.on('user:login', (payload) => { // payload is typed as { userId: string; timestamp: Date } console.log('User logged in:', payload.userId); }); emitter.emit('user:login', { userId: '123', timestamp: new Date() }); // Type-safe // emitter.emit('user:login', { userId: 123 }); // Error: number not assignable to string Advanced Event Validation: type ValidateEventPayload = T extends EventPayload ? T : never; function createTypedEvent( name: E, payload: ValidateEventPayload, E> ): { name: E; payload: EventPayload } { return { name, payload }; } // Usage const loginEvent = createTypedEvent('user:login', { userId: '123', timestamp: new Date() }); Benefits: • Compile-time validation of event payloads • Type-safe event emission and handling • Prevents invalid event data • Excellent IDE autocomplete for events.
Discussion (0)

No comments yet. Be the first to share your thoughts!

Share Your Thoughts
Feedback