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.


By Dev Kapoor, Open Source & Developer Communities Correspondent, Buzzrag

From the BuzzRAG Team

We Watch Tech YouTube So You Don't Have To

Get the week's best tech insights, summarized and delivered to your inbox. No fluff, no spam.

Weekly digestNo spamUnsubscribe anytime

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·3 weeks ago·7 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·4 months ago·6 min read
Python logo and flame icon next to text about benchmarking embedding models, with illustrated brain, magnifying glass,…

Benchmarking Embedding Models: Open Source vs Proprietary

Explore embedding models and their role in data processing, focusing on open-source vs proprietary options.

Dev Kapoor·6 months ago·4 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·2 hours ago·7 min read
Man in KodeKloud shirt gestures while presenting AI agent characters (Zippy, Savvy, Meshy, Cody) on blue background

Building AI Agents From Scratch: An Honest Assessment

A new freeCodeCamp course from KodeKloud walks beginners through LLMs, tool-calling, and real agent architecture using the open-source OpenClaw project.

Dev Kapoor·2 weeks 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·5 months ago·6 min read
Gary Sims wearing a black cap and shirt gestures expressively while discussing AI website building technology against a…

AI Website Builder Creates Full Site From Business Card

Gary Explains tests Readdy AI's ability to generate professional websites from business cards alone. Five minutes, zero code—but what does this mean for web dev?

Dev Kapoor·3 months ago·6 min read
OpenAI GPT 5.5 tutorial with search, code, and terminal icons connected to the ChatGPT logo, highlighting tips and tricks…

GPT 5.5 Isn't Actually Running Unless You Check These Settings

Most people don't realize their new AI model isn't even activated. Here's what TheAIGRID found about GPT 5.5's hidden configuration issues.

Dev Kapoor·3 months ago·6 min read

RAG·vector embedding

2026-07-25
1,728 tokens1536-dimmodel text-embedding-3-small

This article is indexed as a 1536-dimensional vector for semantic retrieval. Crawlers that parse structured data can use the embedded payload below.