error.ts 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import z from "zod"
  2. export abstract class NamedError extends Error {
  3. abstract schema(): z.core.$ZodType
  4. abstract toObject(): { name: string; data: any }
  5. static create<Name extends string, Data extends z.core.$ZodType>(name: Name, data: Data) {
  6. const schema = z
  7. .object({
  8. name: z.literal(name),
  9. data,
  10. })
  11. .meta({
  12. ref: name,
  13. })
  14. const result = class extends NamedError {
  15. public static readonly Schema = schema
  16. public override readonly name = name as Name
  17. constructor(
  18. public readonly data: z.input<Data>,
  19. options?: ErrorOptions,
  20. ) {
  21. super(name, options)
  22. this.name = name
  23. }
  24. static isInstance(input: any): input is InstanceType<typeof result> {
  25. return typeof input === "object" && "name" in input && input.name === name
  26. }
  27. schema() {
  28. return schema
  29. }
  30. toObject() {
  31. return {
  32. name: name,
  33. data: this.data,
  34. }
  35. }
  36. }
  37. Object.defineProperty(result, "name", { value: name })
  38. return result
  39. }
  40. public static readonly Unknown = NamedError.create(
  41. "UnknownError",
  42. z.object({
  43. message: z.string(),
  44. }),
  45. )
  46. }