Skip to content

Instantly share code, notes, and snippets.

@manzt
Last active January 7, 2025 16:06
Show Gist options
  • Save manzt/3702f19abb714e21c22ce48851c75abf to your computer and use it in GitHub Desktop.
Save manzt/3702f19abb714e21c22ce48851c75abf to your computer and use it in GitHub Desktop.
// 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> = T extends new (...args: any[]) => infer R ? R : never;
// deno-lint-ignore no-explicit-any
type UnionInstanceType<T extends readonly (new (...args: any[]) => any)[]> =
InstanceType<T[number]>;
/**
* 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<ErrorClasses> {
if (!errorClasses.some((ErrorClass) => error instanceof ErrorClass)) {
throw error;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment