// Copyright (c) 2024 Trevor Manz - MIT License /** * Type-safe error handling utilities inspired by Python's try/except. * * @module */ // deno-lint-ignore no-explicit-any type InstanceType = T extends new (...args: any[]) => infer R ? R : never; // deno-lint-ignore no-explicit-any type UnionInstanceType any)[]> = InstanceType; /** * Ensures an error matches expected type(s), otherwise rethrows. * * Unmatched errors bubble up, like Python's `except`. Narrows error types for * type-safe property access. * * @example Catch specific error * ```ts * class NotFoundError extends Error { * getStatus() { return 404 } * } * * try { * // This will bubble up since it's not a NotFoundError * throw new Error("Unexpected error"); * } catch (err) { * except(err, NotFoundError); * // Only NotFoundError reaches here * err.getStatus(); * } * ``` * * @example Handle multiple error types * ```ts * class DbError extends Error { * query: string; * } * class NetworkError extends Error { * code: number; * } * * try { * await db.query(); * } catch (err) { * except(err, DbError, NetworkError); * // Only DbError or NetworkError reach here * if (err instanceof DbError) { * console.log(err.query); * } else { * console.log(err.code); * } * } * ``` * * @param error - The error to check * @param errorClasses - Expected error type(s) * @throws The original error if it doesn't match expected type(s) */ export function except< // deno-lint-ignore no-explicit-any ErrorClasses extends readonly (new (...args: any[]) => Error)[], >( error: unknown, ...errorClasses: ErrorClasses ): asserts error is UnionInstanceType { if (!errorClasses.some((ErrorClass) => error instanceof ErrorClass)) { throw error; } }