typescript / expert
Snippet
Structured Error Cause Chaining with Exhaustive Narrowing
This snippet illustrates building domain-specific typed error classes using generic code discriminants combined with native `Error.cause` options. It uses TypeScript's `never` type check to enforce exhaustive compile-time handling of error discrimination branches.
snippet.ts
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class ApplicationError<TCode extends string = string> extends Error {constructor(public readonly code: TCode,message: string,options?: { cause?: unknown }) {super(message, options);this.name = 'ApplicationError';}}type DatabaseError = ApplicationError<'ERR_DB_OFFLINE' | 'ERR_DB_QUERY'>;type NetworkError = ApplicationError<'ERR_NET_TIMEOUT'>;type DomainError = DatabaseError | NetworkError;function handleDomainError(err: DomainError): string {switch (err.code) {case 'ERR_DB_OFFLINE':return 'Database connection lost';case 'ERR_DB_QUERY':return 'Failed to execute query';case 'ERR_NET_TIMEOUT':return 'Network timed out';default: {const _exhaustiveCheck: never = err;throw new Error(`Unhandled error code: ${(_exhaustiveCheck as ApplicationError).code}`);}}}
Breakdown
1
class ApplicationError<TCode extends string = string> extends Error
Extends standard Error with a generic string literal code property for discriminant narrowing.
2
super(message, options);
Passes options containing native nested error causes to the parent Error constructor.
3
type DomainError = DatabaseError | NetworkError;
Composes specific typed error unions for target domain boundaries.
4
const _exhaustiveCheck: never = err;
Triggers a TypeScript compiler error if a new error code is added to DomainError without handling.