diff --git a/src/app/core/fp.ts b/src/app/core/fp.ts new file mode 100644 index 0000000..872f495 --- /dev/null +++ b/src/app/core/fp.ts @@ -0,0 +1,23 @@ +/** + * Tiny native-TS functional toolkit. No dependency — this is the whole "library". + * Reused by every "impossible states" concept in the POC. + */ + +/** Exhaustiveness guard: put in the `default` arm of a union switch. Adding a + new variant without handling it then fails to compile (x is no longer never). */ +export function assertNever(x: never): never { + throw new Error('Unexpected variant: ' + JSON.stringify(x)); +} + +/** A computation that either succeeded with a value or failed with an error. + Plain objects (no classes) to match the signal/httpResource ergonomics. */ +export type Result = + | { readonly ok: true; readonly value: T } + | { readonly ok: false; readonly error: E }; + +export const ok = (value: T): Result => ({ ok: true, value }); +export const err = (error: E): Result => ({ ok: false, error }); + +/** Nominal typing: Brand is assignable from a plain string + only through an explicit cast — so a smart constructor is the only minter. */ +export type Brand = T & { readonly __brand: B };