wellcrafted
Version:
Delightful TypeScript patterns for elegant, type-safe applications
47 lines (45 loc) • 2.34 kB
TypeScript
import { Err } from "./result-_socO0Ud.js";
//#region src/error/types.d.ts
/**
* Base type for any tagged error, used as a minimum constraint.
*/
type AnyTaggedError = {
name: string;
message: string;
};
/**
* Constructor return must include `message: string`.
* JSON serializability is a convention, not enforced at the type level
* (optional fields produce `T | undefined` which breaks `JsonObject`).
*/
type ErrorBody = {
message: string;
};
/**
* Per-key validation: tells the user exactly what `name` will be stamped as.
*
* `name` is stamped by the factory itself (`{ name: K } & ReturnType<fn>`);
* a user-provided `name` would be silently overwritten, so we error loudly.
*/
type ValidateErrorBody<K extends string> = {
message: string;
name?: `The 'name' key is reserved as '${K}'. Remove it.`;
};
/** The config: each key is a variant name, each value is a constructor function. */
type ErrorsConfig = Record<string, (...args: any[]) => ErrorBody>;
/** Validates each config entry, injecting the key-specific `name` reservation message. */
type ValidatedConfig<T extends ErrorsConfig> = { [K in keyof T & string]: T[K] extends ((...args: infer A) => infer R) ? (...args: A) => R & ValidateErrorBody<K> : T[K] };
/** Single factory: takes constructor args, returns Err-wrapped error. */
type ErrorFactory<TName extends string, TFn extends (...args: any[]) => ErrorBody> = { [K in TName]: (...args: Parameters<TFn>) => Err<Readonly<{
name: TName;
} & ReturnType<TFn>>> };
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
/** Return type of `defineErrors`. Maps each config key to its factory. */
type DefineErrorsReturn<TConfig extends ErrorsConfig> = UnionToIntersection<{ [K in keyof TConfig & string]: ErrorFactory<K, TConfig[K]> }[keyof TConfig & string]>;
/** Extract the error type from a single factory. */
type InferError<T> = T extends ((...args: any[]) => Err<infer R>) ? R : never;
/** Extract union of ALL error types from a defineErrors return. */
type InferErrors<T> = { [K in keyof T]: T[K] extends ((...args: any[]) => Err<infer R>) ? R : never }[keyof T];
//#endregion
export { AnyTaggedError, DefineErrorsReturn, ErrorBody, ErrorsConfig, InferError, InferErrors, ValidatedConfig };
//# sourceMappingURL=types-ojNaDB4n.d.ts.map