Comprehensive TypeScript guidance covering compiler configuration, advanced types, utility types, type guards, strict mode workflows, and documentation patterns; use when configuring tsconfig, designing complex generics, making illegal states unrepresentable, fixing type errors, or writing testable and maintainable type-safe APIs.
Overall
score
99%
Does it follow best practices?
Validation for skill structure
Building event emitters with full type safety for event names and payloads.
type Events = {
'user:login': { userId: string; timestamp: Date };
'user:logout': { userId: string };
'data:update': { id: number; data: unknown };
};
class TypedEventEmitter<T extends Record<string, unknown>> {
private listeners = new Map<keyof T, Set<(payload: unknown) => void>>();
on<K extends keyof T>(event: K, handler: (payload: T[K]) => void): void {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
this.listeners.get(event)!.add(handler as (payload: unknown) => void);
}
emit<K extends keyof T>(event: K, payload: T[K]): void {
const handlers = this.listeners.get(event);
if (handlers) {
handlers.forEach(handler => handler(payload));
}
}
off<K extends keyof T>(event: K, handler: (payload: T[K]) => void): void {
const handlers = this.listeners.get(event);
if (handlers) {
handlers.delete(handler as (payload: unknown) => void);
}
}
}
// Usage with full type safety
const emitter = new TypedEventEmitter<Events>();
emitter.on('user:login', (payload) => {
// payload is typed as { userId: string; timestamp: Date }
console.log(payload.userId, payload.timestamp);
});
emitter.emit('user:login', {
userId: '123',
timestamp: new Date()
}); // ✓
// emitter.emit('user:login', { wrong: 'data' }); // ✗ Type errorclass EnhancedEventEmitter<T extends Record<string, unknown>> {
private listeners = new Map<keyof T, Set<(payload: unknown) => void>>();
private onceListeners = new Map<keyof T, Set<(payload: unknown) => void>>();
once<K extends keyof T>(event: K, handler: (payload: T[K]) => void): void {
if (!this.onceListeners.has(event)) {
this.onceListeners.set(event, new Set());
}
this.onceListeners.get(event)!.add(handler as (payload: unknown) => void);
}
emit<K extends keyof T>(event: K, payload: T[K]): void {
// Call regular listeners
const handlers = this.listeners.get(event);
if (handlers) {
handlers.forEach(handler => handler(payload));
}
// Call and remove once listeners
const onceHandlers = this.onceListeners.get(event);
if (onceHandlers) {
onceHandlers.forEach(handler => handler(payload));
this.onceListeners.delete(event);
}
}
}class AsyncEventEmitter<T extends Record<string, unknown>> {
private listeners = new Map<keyof T, Set<(payload: unknown) => Promise<void>>>();
on<K extends keyof T>(event: K, handler: (payload: T[K]) => Promise<void>): void {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
this.listeners.get(event)!.add(handler as (payload: unknown) => Promise<void>);
}
async emit<K extends keyof T>(event: K, payload: T[K]): Promise<void> {
const handlers = this.listeners.get(event);
if (handlers) {
await Promise.all(
Array.from(handlers).map(handler => handler(payload))
);
}
}
}off method to prevent memory leaksInstall with Tessl CLI
npx tessl i pantheon-ai/typescript-advancedreferences