import { expect, test } from "vitest" import { createTaggedErrorClass, matchTaggedError, matchTaggedErrorPartial, } from "#Source/exception/index.ts" class NetworkError extends createTaggedErrorClass("Network")<{ message: string status: number }>() { // } class ValidationError extends createTaggedErrorClass("Validation")<{ message: string field: string }>() { // } type ExampleTaggedError = NetworkError | ValidationError test("matchTaggedError dispatches by tag and throws when a handler is missing", () => { const example1 = new NetworkError({ message: "bad gateway", status: 502, }) as ExampleTaggedError const example2 = new ValidationError({ message: "invalid email", field: "email", }) as ExampleTaggedError const example3 = matchTaggedError(example1, { Network: (error) => `${error.tag}:${error.data.status}`, Validation: (error) => `${error.tag}:${error.data.field}`, }) const example4 = matchTaggedError(example2, { Network: (error) => `${error.tag}:${error.data.status}`, Validation: (error) => `${error.tag}:${error.data.field}`, }) expect(example3).toBe("Network:502") expect(example4).toBe("Validation:email") expect(() => { // @ts-expect-error Testing runtime error when handler is missing return matchTaggedError(example2, { Network: (error) => error.data.status, }) }).toThrow("No handler for tag: Validation") }) test("matchTaggedErrorPartial uses a fallback for unhandled tags", () => { const example1 = new NetworkError({ message: "bad gateway", status: 502, }) as ExampleTaggedError const example2 = new ValidationError({ message: "invalid email", field: "email", }) as ExampleTaggedError const example3 = matchTaggedErrorPartial( example1, { Network: (error) => `${error.tag}:${error.data.status}`, }, (error) => `${error.tag}:${error.message}`, ) const example4 = matchTaggedErrorPartial( example2, { Network: (error) => `${error.tag}:${error.data.status}`, }, (error) => `${error.tag}:${error.data.field}`, ) expect(example3).toBe("Network:502") expect(example4).toBe("Validation:email") })