A Result type in TypeScript
Errors in the return type, so the caller cannot forget them.
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });
const err = <E>(error: E): Result<never, E> => ({ ok: false, error });
function parsePort(raw: string): Result<number, string> {
const port = Number.parseInt(raw, 10);
if (Number.isNaN(port)) return err(`not a number: ${raw}`);
if (port < 1 || port > 65535) return err(`out of range: ${port}`);
return ok(port);
}
function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> {
return result.ok ? ok(fn(result.value)) : result;
}
const parsed = parsePort("8080");
console.log(parsed.ok ? parsed.value : parsed.error);
console.log(map(parsePort("99999"), (n) => n * 2));
How it works
- A discriminated union makes the two outcomes explicit.
- Narrowing on
okgives you the value or the error. - Helpers keep the construction short.
Keywords and builtins used here
ENumberResultTconstfalsefunctionifisNaNnumberparseIntreturnstringtruetype
The run, in numbers
- Lines
- 21
- Characters to type
- 739
- Tokens
- 261
- Three-star pace
- 105 tpm
At the three-star pace of 105 tokens a minute, this run takes about 149 seconds.
Step 1 of 4 in Results & validation, step 5 of 19 in Classes & patterns.