Modeling Result Types
Represent success and failure as data with Result.
Modeling Result Types is a free TypeScript Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Result Type
A Result models an operation that either succeeds with a value or fails with an error, as a discriminated union you can return instead of throwing.
Defining Result
The classic shape uses an ok discriminant. When ok is true there is a value; when false there is an error.
type Result<T, E> =
| { ok: true; value: T }
| { ok: false; error: E };Constructor Helpers
Small ok and err helpers make building results concise and readable, instead of writing the object literals by hand each time.
const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });
const err = <E>(error: E): Result<never, E> => ({ ok: false, error });Returning a Result
A fallible function returns ok(value) or err(error). The return type advertises both possibilities to every caller.
function divide(a: number, b: number): Result<number, string> {
return b === 0 ? err("divide by zero") : ok(a / b);
}Narrowing on ok
Checking result.ok narrows the union. Inside the true branch TypeScript knows value exists; inside the false branch it knows error exists.
const r = divide(10, 2);
if (r.ok) console.log(r.value); // 5
else console.log(r.error);The Discriminant Drives Safety
The ok field is the discriminant that lets the compiler pick the right branch. You cannot access value without proving ok is true first.
const r = divide(1, 0);
// r.value here is a type error until we check r.ok
if (!r.ok) console.log("err:", r.error);Typed Errors
Errors can be richer than strings. Using a typed error union lets callers handle each kind precisely after narrowing.
type DivErr = { kind: "zero" } | { kind: "overflow" };
function div(a: number, b: number): Result<number, DivErr> {
if (b === 0) return err({ kind: "zero" });
return ok(a / b);
}Exhaustive Error Handling
Because the error type is a union, a switch on its discriminant can be checked for exhaustiveness, ensuring every failure mode is handled.
const r = div(1, 0);
if (!r.ok) {
switch (r.error.kind) {
case "zero": console.log("no zero"); break;
case "overflow": console.log("too big"); break;
}
}A Default-Value Helper
Sometimes you just want the value or a fallback. A small unwrapOr reads cleanly and keeps the failure handling local.
function unwrapOr<T, E>(r: Result<T, E>, fallback: T): T {
return r.ok ? r.value : fallback;
}
console.log(unwrapOr(divide(1, 0), -1)); // -1Result vs Throwing
Result moves failure into the return type, so callers must engage with it. The trade-off is more explicit code, which is usually worth it for expected errors.
A Complete Example
Putting it together: define helpers, return results, and narrow before use. The compiler guarantees the error branch is acknowledged.
function safeParse(s: string): Result<number, string> {
const n = Number(s);
return Number.isNaN(n) ? err("NaN") : ok(n);
}
const p = safeParse("42");
console.log(p.ok ? p.value : p.error); // 42Quick Check
Quick check on this lesson.
Recap
Result<T, E> is a discriminated union { ok: true; value } or { ok: false; error }. Build it with ok/err helpers and narrow on ok to safely access value or error, with typed errors enabling exhaustive handling.
Frequently asked questions
Is the “Modeling Result Types” lesson free?
Yes — the full text of “Modeling Result Types” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.
What will I learn in “Modeling Result Types”?
Represent success and failure as data with Result. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start TypeScript Academy?
No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Modeling Result Types” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this TypeScript Academy lesson?
Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The Problem with Throwing Errors
- Modeling Result Types
- Option and Maybe Types
- Railway-Oriented Programming