Lab 11: Advanced Error Handling
Step 1: Environment Setup
docker run -it --rm node:20-alpine sh
npm install -g typescript ts-node
mkdir lab11 && cd lab11
npm init -y
npm install neverthrow
echo '{"compilerOptions":{"module":"commonjs","target":"es2020","strict":true,"esModuleInterop":true}}' > tsconfig.jsonStep 2: assertNever for Exhaustive Checks
// exhaustive.ts
// assertNever: TypeScript ensures this is never called
function assertNever(x: never, message?: string): never {
throw new Error(message ?? `Unexpected value: ${JSON.stringify(x)}`);
}
// Discriminated union — all variants must be handled
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'rectangle'; width: number; height: number }
| { kind: 'triangle'; base: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
case 'rectangle':
return shape.width * shape.height;
case 'triangle':
return 0.5 * shape.base * shape.height;
default:
// If you add a new Shape variant without handling it here,
// TypeScript will error: "Argument of type X is not assignable to parameter of type never"
return assertNever(shape);
}
}
type Color = 'red' | 'green' | 'blue';
function getHex(color: Color): string {
switch (color) {
case 'red': return '#FF0000';
case 'green': return '#00FF00';
case 'blue': return '#0000FF';
default: return assertNever(color);
}
}
console.log('Circle area:', area({ kind: 'circle', radius: 5 }).toFixed(2));
console.log('Rectangle area:', area({ kind: 'rectangle', width: 4, height: 6 }));
console.log('Red hex:', getHex('red'));
console.log('Blue hex:', getHex('blue'));Step 3: Result Monad from Scratch
Step 4: Typed Error Unions
Step 5: neverthrow Library
Step 6: Type-Safe Error Serialization
Step 7: Composing Error Handlers
Step 8: Capstone — Production Error System
Summary
Pattern
Code
Benefit
Last updated
