1. Build Result<T,E> with helpers map, mapError, match.
Model success and failure without exceptions. map transforms the success value, mapError transforms the error, and match runs the right handler at call site. This leads to clear, explicit error handling.
type Ok<T> = { ok: true; value: T };
type Err<E> = { ok: false; error: E };
export type Result<T, E> = Ok<T> | Err<E>;
export const ok = <T>(v: T): Result<T, never> => ({ ok: true, value: v });
export const err = <E>(e: E): Result<never, E> => ({ ok: false, error: e });
export const map = <T, U, E>(r: Result<T,E>, f: (x:T)=>U): Result<U,E> =>
r.ok ? ok(f(r.value)) : r;
export const mapError = <T, E, F>(r: Result<T,E>, g: (e:E)=>F): Result<T,F> =>
r.ok ? r : err(g(r.error));
export const match = <T,E,R>(r: Result<T,E>, onOk:(v:T)=>R, onErr:(e:E)=>R): R =>
r.ok ? onOk(r.value) : onErr(r.error);