Type-safe routing with Typescript and Route Maps

mattpocockuk

Matt Pocock

Posted on July 29, 2020

Type-safe routing with Typescript and Route Maps

Routing in web apps can be a subtle, but persistent source of bugs. You think you've updated every reference to a route you're changing, and BAM. You've caused a bug in some unrelated part of your app.

This gets worse when you need to add path parameters (/user/:id/edit) and search parameters (/auth?redirectPath=somewhere). Usually, this leads to a ton of string concatenation clogging up your code, and a mess of routes that are hard to maintain.

That's why I built make-route-map, an npm package which helps get your routing under control. It's 100% Typescript, and it lets you create a gorgeous, clean API for your routing which has type-safe routes, path parameters and search parameters.

I can't tell you how much stress it's saved me already. Refactoring or removing a route no longer takes dozens of find-in-files to remove the references. All that stress is Typescripted away.

The Basics

import { makeRouteMap } from 'make-route-map';

const routeMap = makeRouteMap({
  users: {
    path: '/users',
  },
  editUser: {
    path: '/users/:id/edit',
    params: {
      id: true,
    },
  },
  auth: {
    path: '/auth',
    search: {
      redirectPath: true,
    },
  },
});

console.log(routeMap.users());
// '/users'

console.log(routeMap.editUser({ params: { id: '240' } });
// '/users/240/edit'

console.log(
  routeMap.auth({
    search: { redirectPath: 'somewhere' },
  }),
);
// /auth?redirectPath=somewhere

Enter fullscreen mode Exit fullscreen mode

The makeRouteMap function just creates a set of helpers which pull out the routes. You can pass in path parameters and search parameters.

Navigating

makeNavigate can take in a routeMap and a function to send you to a route, and will navigate you there when it's called.

const goToRoute = route => {
  window.location.href = route;
};

const navigate = makeNavigate(routeMap, goToRoute);

// This would take the user to '/users/240/edit'
navigate.editUser({
  params: {
    id: '240',
  },
});
Enter fullscreen mode Exit fullscreen mode

This means you can plug in navigate into your current navigation implementation, like history.push.

Try it out

The repo
The package

Let me know how you get on, and if you have any requests for the API. I'm so excited to have a pattern that's been working wonders for us public available.

💖 💪 🙅 🚩
mattpocockuk
Matt Pocock

Posted on July 29, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related