0Pricing
TypeScript Academy · Lesson

A Mini Type-Level Route Parser

Parse route paths into typed parameter objects.

A Mini Type-Level Route Parser is a free TypeScript Academy lesson on CoddyKit — 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, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The Goal

We build a route parser that reads a path like "users/:id/posts/:postId" and produces a typed params object { id: string; postId: string }, entirely at compile time. This is a real pattern used by typed routers.

type Params = ParseRoute<"users/:id/posts/:postId">;
// Goal: { id: string; postId: string }

Recognizing a Parameter

A path segment is a parameter when it starts with ":". We match that prefix with a template literal and infer the parameter name after the colon.

Notation: real TypeScript writes template literal types with backtick-delimited strings containing dollar-brace holes. In these snippets we show that pattern as Tpl<...>, listing each part in order; e.g. a backtick template matching the literal prefix then Rest appears as Tpl<'prefix', infer Rest>.

type ParamName<S> = S extends Tpl<':', infer Name> ? Name : never;
// Tpl<...> denotes a backtick template literal type: a colon then Name

type X = ParamName<':id'>;   // 'id'
type Y = ParamName<'users'>; // never

Splitting the Path

First split the route into segments on "/", reusing the Split type. Each segment is then either a literal or a parameter.

type Split<S extends string, Sep extends string> =
  S extends Tpl<infer H, Sep, infer T> ? [H, ...Split<T, Sep>] : [S];
// Tpl<H, Sep, T> = a template literal type matching H, then Sep, then T

type Segs = Split<'users/:id', '/'>; // ['users', ':id']

Direct Template Recursion

We can also parse the raw string without splitting first, by matching one segment at a time. Match up to the next "/", handle that segment, then recurse on the rest.

type ParseRoute<S extends string> =
  S extends Tpl<infer Seg, '/', infer Rest>
    ? SegParam<Seg> & ParseRoute<Rest>
    : SegParam<S>;
// Tpl<Seg, '/', Rest> matches a segment, a slash, then the rest

Per-Segment Parameter

The helper turns a single segment into either a one-property object (if it is a parameter) or an empty object (if it is a literal).

type SegParam<S extends string> =
  S extends Tpl<':', infer Name> ? { [K in Name]: string } : {};
// Tpl<':', Name> matches a colon followed by the param name

type X = SegParam<':id'>;   // { id: string }
type Y = SegParam<'posts'>; // {}

Combining With Intersection

Each segment contributes its params via intersection. Empty objects vanish in an intersection, so only real parameters remain in the final type.

type Params = ParseRoute<"users/:id/posts/:postId">;
// { id: string } & {} & { postId: string } & {}
// = { id: string; postId: string }

Tracing the Parse

For "users/:id/posts/:postId":

  • Seg "users" -> {} , recurse on ":id/posts/:postId"
  • Seg ":id" -> { id: string }, recurse on "posts/:postId"
  • Seg "posts" -> {}, recurse on ":postId"
  • Seg ":postId" -> { postId: string }, base case
type Final = { id: string } & { postId: string };

Cleaning the Result

The intersection of objects displays awkwardly. A "prettify" helper flattens it into a single clean object type using a mapped type over its keys.

type Prettify<T> = { [K in keyof T]: T[K] } & {};

type Clean = Prettify<ParseRoute<"users/:id">>; // { id: string }

Using the Parser

Plug the parsed type into a function so the handler receives correctly typed params. Passing the wrong key becomes a compile error.

declare function route<P extends string>(
  path: P,
  handler: (params: Prettify<ParseRoute<P>>) => void
): void;

route("users/:id", p => { const id: string = p.id; });

Typed Params Payoff

The compiler now derives params from the route string itself. Rename a parameter in the path and every handler updates its expected keys automatically. No manual interface, no drift between route and handler.

route("users/:userId", p => {
  const u = p.userId; // ok
  // const x = p.id; // error: id does not exist
});

Extending the Parser

This mini parser is the seed of a full typed router. You can add typed values (number params), wildcards, and optional segments, all by enriching the per-segment helper with more template patterns. The recursive-template structure stays the same.

type SegParam2<S extends string> =
  S extends Tpl<':', infer N, '(number)'> ? { [K in N]: number }
  : S extends Tpl<':', infer N> ? { [K in N]: string }
  : {};
// Tpl<...> stands for a backtick template literal type pattern

Quick Check

Test your understanding of the route parser.

Recap

You built a compile-time route parser.

  • Match each segment with recursive template literal inference.
  • Parameter segments (:name) become { name: string }.
  • Literal segments become {} and vanish in the intersection.
  • Prettify flattens the result into clean params.

Course 25 next: end-to-end type safety with tRPC.

Frequently asked questions

Is the “A Mini Type-Level Route Parser” lesson free?

Yes — the full text of “A Mini Type-Level Route Parser” 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 “A Mini Type-Level Route Parser”?

Parse route paths into typed parameter objects. 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 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “A Mini Type-Level Route Parser” 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

  1. Parser Combinator Concepts
  2. Type-Level String Splitting
  3. Parsing with Template Literals
  4. A Mini Type-Level Route Parser
← Back to TypeScript Academy