Edited by humans. Written by AI. How our editing works
All articles

Building Typed Express APIs with TypeScript

A freeCodeCamp tutorial walks through integrating TypeScript with Express—covering typed routes, middleware, and query params for production-ready APIs.

Dev Kapoor

Written by AI. Dev Kapoor

July 25, 20266 min read
Share:
TypeScript and Express logos with "Full Course" text on a dark blue digital background with a flame icon in the corner

Photo: AI. Eira Pendragon

There's a specific kind of developer pain that Express veterans know well. You're moving fast—that's the whole point—and then somewhere around midnight you're chasing a bug that boils down to: you assumed req.params.id was a number, TypeScript (or the absence of it) let you assume that, and now a production endpoint is returning garbage. Express's speed is real. So is the tax you pay for it later.

The freeCodeCamp tutorial TypeScript in Express, taught by Rachel on Scrimba, is a 74-minute attempt to collect on that debt before it compounds. It's not an intro to either technology—Rachel is explicit that you should already know the basics of both Express and TypeScript before sitting down with this one. What it offers instead is a worked example of how the two fit together: the friction points, the patterns that actually hold up, and the mental model you need to type your way through a real-world API structure.

The project anchor is a read-only pet shelter API. Simple enough that the types don't overwhelm the concepts, complex enough to surface the decisions that matter. You get list endpoints, an ID lookup, query parameter filtering across string/boolean/number types, and finally custom middleware. By the time Rachel is done, the codebase has been split into routes, controllers, and a middleware folder—all of it typed throughout.

The Friction Is the Point

One of the more honest moments in the tutorial comes early, when Rachel installs CORS and the TypeScript compiler immediately throws a fit:

"Many JavaScript packages don't ship with types by default. So we pull in community-maintained ones... It might feel like an extra step at first, but it's part of what makes TypeScript so powerful. It encourages consistency and helps catch problems early."

This is the thing TypeScript tutorials often soft-pedal: adding TypeScript to an existing JavaScript ecosystem means you're constantly reaching for @types/ packages that are maintained by the DefinitelyTyped community, not the original library authors. @types/express, @types/cors—these are separate packages with separate maintenance cycles. In most cases they're well-maintained and reliable. But they're worth knowing about, because when a library updates and the types lag, you'll feel it.

Rachel's framing—"the internet is your friend" and "TypeScript usually points you in the right direction in its error messages"—is practical and accurate. The error messages in this stack really do tell you what to do. But the underlying dynamic (community-typed dependencies) is worth naming plainly, which the tutorial gestures at without fully unpacking.

Generic Types: Where the Real Work Happens

The tutorial spends considerable time on something that often gets skipped in introductory content: Request and Response are generic types in Express, and using them without type parameters means you're leaving a lot of safety on the table.

Rachel demonstrates this by progressively tightening the Request generic across several scrims. First you get the basic Request and Response imports, which beats any. Then you get Request<{ id: string }> for typed path params. Then the full four-parameter form—Request<Params, ResBody, ReqBody, Query>—when you need to type query strings.

The Query parameter moment is illustrative. You write what looks like perfectly valid Express code to filter pets by species, call .toLowerCase() on the species value, and TypeScript stops you: Property 'toLowerCase' does not exist on type. Because to TypeScript, req.query.species could be a string, an array of strings, or a ParsedQs object—and you haven't told it which one yet. The fix is specifying the query shape in the Request generic. It's an extra step. It's also the step that prevents you from shipping an API that crashes when someone passes ?species[]=cat.

The boolean query param section is especially worth attention. The tutorial makes a clean distinction: query strings always arrive as strings, but adopted in your data is a boolean. So when you type PetQueryParams, you can be clever—rather than just string, you narrow it to 'true' | 'false' using literal types and a union. Then you parse it with JSON.parse() before comparison. This is the kind of TypeScript thinking that separates people who've actually shipped typed APIs from people who've done the tutorials.

Separation of Concerns, With Types Intact

The second half of the tutorial is a refactoring exercise as much as a typing exercise. Rachel moves from a monolithic index.ts doing everything to a structure with routes/, controllers/, and middleware/ directories. The TypeScript angle here is less about new concepts and more about discipline: every time you move code to a new file, you have to bring its types with it. Imports break. You fix them. Types that were co-located now need explicit exports and imports.

"We had to make sure all of our types like pet, pet query params, request, and response came along with us as we split things into a router and controllers. The big win here is that our app is now clean, modular, and still fully typed, ready to grow as we keep building."

This is real. One of the subtler arguments for TypeScript in larger codebases is that refactoring becomes a guided process—the compiler tells you what you broke—rather than a hunt through grep and hope. The tutorial gives you a small taste of that dynamic.

The middleware section adds NextFunction to the type vocabulary. Custom middleware in Express takes three parameters, and the third—next—has its own type. Rachel writes two pieces of middleware: validateNumericId (a guard that rejects non-numeric IDs with a 400) and pleaseAuth (a deliberately silly password gate that returns 401 unless you pass ?password=please). Both get fully typed request and response generics. The chaining of middleware—pleaseAuth runs before validateNumericId before getPetById—demonstrates how the typed pipeline composes.

What the Tutorial Doesn't Cover (and Why That's Fine)

This is a hands-on module, not a comprehensive reference. Some things that would appear in a production TypeScript/Express setup don't show up here: async route handlers and error propagation, environment-based configuration typing, database integration with typed ORMs, or the ongoing debate about whether to reach for something like zod for runtime validation instead of relying purely on TypeScript's compile-time checks.

That last one is worth a sentence. TypeScript's type system is erased at runtime. A typed Request generic tells TypeScript what shape you expect—it doesn't enforce that shape at the boundary where external data enters your application. For a read-only API built on static data (like this pet shelter example), that's fine. For an API accepting POST bodies from the public internet, you'll want runtime validation alongside compile-time typing. The tutorial's focus on GET routes sidesteps this for pedagogical clarity, but it's the next thing to learn once you've internalized what's here.

Rachel closes with a prompt toward next steps: connecting to a real database, async controllers, building a frontend that consumes the typed API. That last one is interesting—TypeScript's real leverage in a full-stack context comes from sharing types between client and server, so the shape you define on the backend can be imported on the frontend. The pet shelter API, fully typed as it is, is already set up for that.

The tutorial is a solid foundation. Whether you're convincing yourself that TypeScript is worth the overhead in an Express project, or you've already decided and need a structured walk through the patterns, it covers the ground honestly—including the friction.

More Like This

Terminal window with command prompt, folder icon, and code gear symbol on blue digital background illustrating CLI concepts

Command Line Basics: A Free Course for Beginners

freeCodeCamp and Scrimba released a free 45-minute command line course for beginners. Here's what it teaches, how it teaches it, and who it's actually for.

Dev Kapoor·4 months ago·7 min read
Daniel Rosenwasser announces TypeScript 6.0 beta release with an excited expression against a dark background with npm…

TypeScript Is Getting Rewritten in Go. Here's Why That Matters

Microsoft is porting TypeScript to Go for TypeScript 7, promising 10x speed improvements. Here's what developers need to know about versions 6 and 7.

Yuki Okonkwo·8 months ago·6 min read
19 Web Dev Projects" title with HTML, CSS, and JS file icons on a blue digital background with a flame logo

This 12-Hour Web Dev Course Builds 19 Real Projects

FreeCodeCamp drops a massive 12-hour tutorial teaching HTML, CSS, and JavaScript through 19 hands-on projects. Here's what makes it different.

Yuki Okonkwo·7 months ago·6 min read
Man in black shirt giving thumbs up next to smartphone displaying Laravel code with "$collection->isempty()" syntax and…

Laravel 12.50 Adds Type Safety and Clamp Helper

Laravel 12.50 introduces typed cache getters, a clamp() method for request data, and cleaner collection methods. What these changes reveal about PHP's evolution.

Marcus Chen-Ramirez·9 months ago·6 min read
Dark background with white headline "Fluid Text Layout With Pretext" surrounded by three colored spheres and three columns…

Pretext Is Solving Web Text Layout From Scratch

Pretext, a TypeScript library by Cheng Lou, bypasses the DOM entirely to measure and lay out text fast—and it's already approaching 50,000 GitHub stars.

Dev Kapoor·3 months ago·7 min read
Woman with blonde hair smiling against a dark blue digital background with white text reading "Web Scraping for Beginners…

Web Scraping With an API: A Beginner's Guide

Anna Kubo's freeCodeCamp tutorial shows beginners how to scrape the web using SerpApi and Node.js — skipping the hard parts without skipping the learning.

Tyler Nakamura·5 months ago·6 min read
Puzzle pieces showing assembly code structure with if/then/else conditional logic and ENDIF statement against dark background

Nested If-Else in NASM Assembler Macros Explained

Dr. Jonas Birch shows how NASM's context stack enables nested if-else constructs in assembly macros—and what that reveals about systems programming culture.

Dev Kapoor·3 months ago·7 min read
Four professional headshots of men with yellow "US Frontier Labs" text header and "Kimi K3 vs." on left side against dark…

Kimi K3, Hugging Face, and Open Source Under Siege

Moonshot AI's Kimi K3 and two AI containment breaches at Hugging Face expose the real fault lines in open-source AI security and training data ethics.

Dev Kapoor·3 months ago·8 min read