Result Type
Fizzy MCP uses a Result type for operations that can fail. This provides type-safe error handling without throwing exceptions.
Overview
typescript
type Result<T, E> = Ok<T> | Err<E>;
interface Ok<T> {
ok: true;
value: T;
}
interface Err<E> {
ok: false;
error: E;
}Creating Results
Success
typescript
import { ok } from '@fizzy-do-mcp/shared';
const result = ok({ id: '123', name: 'My Board' });
// Type: Result<{ id: string; name: string }, never>Error
typescript
import { err } from '@fizzy-do-mcp/shared';
const result = err({ code: 'NOT_FOUND', message: 'Board not found' });
// Type: Result<never, { code: string; message: string }>Type Guards
isOk
Check if result is successful:
typescript
import { isOk } from '@fizzy-do-mcp/shared';
const result = await client.boards.list();
if (isOk(result)) {
// TypeScript knows result.value is Board[]
console.log(result.value);
}isErr
Check if result is an error:
typescript
import { isErr } from '@fizzy-do-mcp/shared';
const result = await client.cards.getByNumber(42);
if (isErr(result)) {
// TypeScript knows result.error is FizzyError
console.log(result.error.message);
}Unwrapping
unwrap
Get the value or throw if error:
typescript
import { unwrap } from '@fizzy-do-mcp/shared';
const result = await client.boards.list();
const boards = unwrap(result); // Throws if errorunwrapOr
Get the value or return a default:
typescript
import { unwrapOr } from '@fizzy-do-mcp/shared';
const result = await client.cards.list();
const cards = unwrapOr(result, []); // Returns [] if errorunwrapErr
Get the error or throw if success:
typescript
import { unwrapErr } from '@fizzy-do-mcp/shared';
const result = await client.boards.deleteBoard('invalid_id');
const error = unwrapErr(result); // Throws if successPattern Matching
match
Handle both cases with a single call:
typescript
import { match } from '@fizzy-do-mcp/shared';
const result = await client.cards.getByNumber(42);
const message = match(result, {
ok: (card) => `Found: ${card.title}`,
err: (error) => `Error: ${error.message}`,
});matchAsync
Async version for async handlers:
typescript
import { matchAsync } from '@fizzy-do-mcp/shared';
const result = await client.boards.getById('board_id');
await matchAsync(result, {
ok: async (board) => {
await saveToCache(board);
},
err: async (error) => {
await logError(error);
},
});Transformations
map
Transform the success value:
typescript
import { map } from '@fizzy-do-mcp/shared';
const result = await client.boards.list();
const names = map(result, (boards) => boards.map((b) => b.name));
// Type: Result<string[], FizzyError>mapErr
Transform the error:
typescript
import { mapErr } from '@fizzy-do-mcp/shared';
const result = await client.cards.getByNumber(42);
const mapped = mapErr(result, (error) => ({
...error,
timestamp: new Date(),
}));flatMap
Chain operations that return Results:
typescript
import { flatMap } from '@fizzy-do-mcp/shared';
const result = await client.boards.getById('board_id');
const columnsResult = flatMap(result, (board) =>
client.columns.list(board.id)
);Combining Results
combine
Combine multiple results into one:
typescript
import { combine } from '@fizzy-do-mcp/shared';
const results = await Promise.all([
client.boards.getById('board_1'),
client.boards.getById('board_2'),
]);
const combined = combine(results);
// Type: Result<Board[], FizzyError>
// Returns first error if any failBest Practices
- Prefer type guards over unwrap: Use
isOk/isErrfor explicit handling - Use
unwrapOrfor optional data: Provide sensible defaults - Use
matchfor exhaustive handling: Ensures both cases are handled - Chain with
flatMap: Compose operations that can fail