Command Palette
Search for a command to run...
Here's a discriminated union Result type with full type narrowing:
typescripttype Result<T, E = Error> = | { ok: true; data: T } | { ok: false; error: E }; // Helper constructors function ok<T>(data: T): Result<T, never> { return { ok: true, data }; } function err<E>(error: E): Result<never, E> { return { ok: false, error }; } // Usage with automatic type narrowing async function fetchConversations(): Promise<Result<Conversation[]>> { try { const response = await fetch('/api/conversations'); if (!response.ok) { return err(new Error(`HTTP ${response.status}`)); } const data = await response.json(); return ok(data); } catch (e) { return err(e instanceof Error ? e : new Error(String(e))); } } // Consumer code — TypeScript narrows automatically const result = await fetchConversations(); if (result.ok) { // TypeScript knows: result.data is Conversation[] console.log(result.data.length); } else { // TypeScript knows: result.error is Error console.error(result.error.message); }
This pattern avoids try-catch at the call site and makes error handling explicit in the type system.