Result<T, E>: errors without exceptions
The Result<T, E> type is either a success { ok: true, value } or a failure { ok: false, error }. Write precisely typed helpers for it.
ok(value) and err(error) create a result, mapResult(result, fn) transforms a success value and passes a failure through unchanged (without calling fn), and unwrapOr(result, fallback) returns the value or the fallback. The error type should carry over to the result of mapResult.
Ctrl+Enter runs the tests. Tab indents; to leave the editor with the keyboard, press Esc and then Tab. Your code is saved in this browser.
Tests (8)
Type tests are checked by the TypeScript compiler in strict mode. Expect<Equal<A, B>> passes when the types match exactly, and // @ts-expect-error passes when the next line does not compile. The first run downloads the compiler, so it takes a few seconds.
- types
const r = ok(42); type _ = Expect<Equal<typeof r, Result<number, never>>>;
- types
const e = err('not found'); type _ = Expect<Equal<typeof e, Result<never, string>>>;
- types
const r = {} as Result<number, string>; const m = mapResult(r, (n) => String(n)); type _ = Expect<Equal<typeof m, Result<string, string>>>;
- types
const r = {} as Result<number, string>; const v = unwrapOr(r, 0); type _ = Expect<Equal<typeof v, number>>;
expect(ok(1)).toEqual({ ok: true, value: 1 }); expect(err('x')).toEqual({ ok: false, error: 'x' });
expect(mapResult(ok(2), (n) => n * 10)).toEqual({ ok: true, value: 20 });
const f = fn((n) => n * 10); const failure = err('bad'); expect(mapResult(failure, f)).toEqual({ ok: false, error: 'bad' }); expect(f).toHaveBeenCalledTimes(0);
expect(unwrapOr(ok(5), 0)).toBe(5); expect(unwrapOr(err('bad'), 0)).toBe(0);