import { bench, describe } from 'vitest'; import { STANDARD } from '../helpers/bench-options.js'; import { ok, err, ntOk, ntErr, TsOk, TsErr, OxOk, OxErr, E, pipe, TmResult, } from '../helpers/imports.js'; // --------------------------------------------------------------------------- // 5-step pipeline — success path // --------------------------------------------------------------------------- describe('Result chaining — 5-step pipeline (all succeed)', () => { bench('native-monad', () => { ok(42) .map(x => x * 2) .flatMap(x => (x > 0 ? ok(x) : err('negative'))) .map(x => ({ value: x })) .flatMap(x => ok({ ...x, label: 'result' })) .map(x => JSON.stringify(x)); }, STANDARD); bench('neverthrow', () => { ntOk(42) .map(x => x * 2) .andThen(x => (x > 0 ? ntOk(x) : ntErr('negative'))) .map(x => ({ value: x })) .andThen(x => ntOk({ ...x, label: 'result' })) .map(x => JSON.stringify(x)); }, STANDARD); bench('ts-results-es', () => { TsOk(42) .map(x => x * 2) .andThen(x => (x > 0 ? TsOk(x) : TsErr('negative'))) .map(x => ({ value: x })) .andThen(x => TsOk<{ value: number; label: string }, string>({ ...x, label: 'result' })) .map(x => JSON.stringify(x)); }, STANDARD); bench('oxide.ts', () => { OxOk(42) .map(x => x * 2) .andThen(x => (x > 0 ? OxOk(x) : OxErr('negative'))) .map(x => ({ value: x })) .andThen(x => OxOk({ ...x, label: 'result' })) .map(x => JSON.stringify(x)); }, STANDARD); bench('fp-ts', () => { pipe( E.right(42), E.map(x => x * 2), E.flatMap(x => (x > 0 ? E.right(x) : E.left('negative'))), E.map(x => ({ value: x })), E.flatMap(x => E.right({ ...x, label: 'result' })), E.map(x => JSON.stringify(x)), ); }, STANDARD); bench('true-myth', () => { TmResult.ok(42) .map(x => x * 2) .andThen(x => (x > 0 ? TmResult.ok(x) : TmResult.err('negative'))) .map(x => ({ value: x })) .andThen(x => TmResult.ok({ ...x, label: 'result' })) .map(x => JSON.stringify(x)); }, STANDARD); }); // --------------------------------------------------------------------------- // 10-step pipeline — error at step 1 (9 no-ops) // --------------------------------------------------------------------------- describe('Result chaining — error at step 1, 9 no-op maps', () => { const nmErr = err('fail'); const ntErrVal = ntErr('fail'); const tsErr = TsErr('fail'); const oxErr = OxErr('fail'); const fpErr = E.left('fail'); const tmErr = TmResult.err('fail'); const fn = (x: number) => x + 1; bench('native-monad', () => { nmErr.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn); }, STANDARD); bench('neverthrow', () => { ntErrVal.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn); }, STANDARD); bench('ts-results-es', () => { tsErr.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn); }, STANDARD); bench('oxide.ts', () => { oxErr.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn); }, STANDARD); bench('fp-ts', () => { pipe(fpErr, E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn)); }, STANDARD); bench('true-myth', () => { tmErr.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn); }, STANDARD); }); // --------------------------------------------------------------------------- // 20-step deep map chain — success path // --------------------------------------------------------------------------- describe('Result chaining — 20 maps on Ok', () => { const fn = (x: number) => x + 1; bench('native-monad', () => { let r = ok(0); for (let i = 0; i < 20; i++) r = r.map(fn); }, STANDARD); bench('neverthrow', () => { let r = ntOk(0); for (let i = 0; i < 20; i++) r = r.map(fn); }, STANDARD); bench('ts-results-es', () => { let r = TsOk(0); for (let i = 0; i < 20; i++) r = r.map(fn) as any; }, STANDARD); bench('oxide.ts', () => { let r = OxOk(0); for (let i = 0; i < 20; i++) r = r.map(fn) as any; }, STANDARD); bench('fp-ts', () => { let r = E.right(0) as E.Either; for (let i = 0; i < 20; i++) r = pipe(r, E.map(fn)); }, STANDARD); bench('true-myth', () => { let r = TmResult.ok(0); for (let i = 0; i < 20; i++) r = r.map(fn) as any; }, STANDARD); });