Railway-Oriented Programming
Chain operations that may fail without try/catch.
Railway-Oriented Programming is a free TypeScript Academy lesson on CoddyKit. This is lesson 4 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, and your progress syncs across the web and the CoddyKit app. The TypeScript Academy course includes 4 lessons in total.
The Railway Metaphor
Railway-oriented programming pictures a computation as two parallel tracks: a success track and a failure track. Once you switch to failure, you stay there, skipping the rest.
Chaining Result Functions
Each step takes a value and returns a Result. We want to connect steps so that the first failure short-circuits the chain and is carried to the end.
type Result<T, E> = { 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 });map: Transform the Success Value
map applies a plain function to the value when the Result is ok, and passes failures through unchanged. It stays on the success track.
function map<T, U, E>(r: Result<T, E>, f: (t: T) => U): Result<U, E> {
return r.ok ? ok(f(r.value)) : r;
}
console.log(map(ok(2), n => n + 1)); // { ok: true, value: 3 }flatMap: Chain Fallible Steps
When the next step itself returns a Result, use flatMap (also called andThen). It avoids nesting Results and short-circuits on failure.
function flatMap<T, U, E>(r: Result<T, E>, f: (t: T) => Result<U, E>): Result<U, E> {
return r.ok ? f(r.value) : r;
}Why flatMap Not map
If you used map with a Result-returning function you would get Result<Result<U,E>,E>. flatMap flattens that one level, keeping a single Result.
Short-Circuiting on First Error
As soon as a step returns err, every later flatMap passes it through untouched. The remaining steps never run, exactly like switching to the failure track.
const start = err("boom") as Result<number, string>;
const out = flatMap(start, n => ok(n + 1));
console.log(out); // { ok: false, error: "boom" }Building a Pipeline
Compose validation steps, each returning a Result. The first failure becomes the pipeline's result; if all pass, the success value flows to the end.
function parseNum(s: string): Result<number, string> {
const n = Number(s);
return Number.isNaN(n) ? err("not a number") : ok(n);
}
function positive(n: number): Result<number, string> {
return n > 0 ? ok(n) : err("must be positive");
}Running the Pipeline
Chaining flatMap threads the value through each fallible step. A failure anywhere stops the chain and surfaces that error.
const good = flatMap(parseNum("5"), positive);
console.log(good); // { ok: true, value: 5 }
const bad = flatMap(parseNum("-3"), positive);
console.log(bad); // { ok: false, error: "must be positive" }Combining map and flatMap
Use flatMap for steps that can fail and map for pure transforms. Together they keep the happy path linear and the errors automatic.
const result = map(flatMap(parseNum("10"), positive), n => n * 2);
console.log(result); // { ok: true, value: 20 }No try/catch Needed
The whole pipeline expresses success and failure through values. There is no try/catch, and the type of every step makes the error path explicit and unavoidable.
Why It Scales
Railway-oriented code keeps complex workflows readable: each step is small and pure, errors propagate automatically, and adding a step does not complicate existing error handling.
Quick Check
Quick check on this lesson.
Recap
Railway-oriented programming chains Result-returning steps with map (transform success) and flatMap/andThen (chain fallible steps, flattening nested Results). The first err short-circuits the rest, propagating to the end with no try/catch.
Learn TypeScript with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 101
- Lessons
- 352
Frequently Asked Questions
Is the “Railway-Oriented Programming” lesson free?
Yes — the full text of “Railway-Oriented Programming” is free to read here on the web. 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. The TypeScript Academy course includes 4 lessons in total.
What will I learn in “Railway-Oriented Programming”?
Chain operations that may fail without try/catch. 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, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
How long does the “Railway-Oriented Programming” 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