DEV Community

Cover image for How to Use Typed Routes in Next.js
Fabrikapp
Fabrikapp

Posted on

How to Use Typed Routes in Next.js

Next.js is a powerful React framework that simplifies the creation of web applications by providing a set of conventions and built-in functionalities. One of the key features of Next.js is its routing system, which allows developers to create pages and navigate between them with ease. With the introduction of typed routes, Next.js enhances the developer experience by providing type safety for routing, especially when using TypeScript.

Understanding Typed Routes in Next.js

Typed routes in Next.js are an experimental feature that provides statically typed links within your application. This feature is part of the Next.js App Router and requires TypeScript to be used in your project. The main advantage of typed routes is that they help ensure that the links within your application are correct at compile time, reducing the likelihood of runtime errors due to incorrect URLs or missing query parameters.

To enable typed routes in your Next.js project, you need to set the typedRoutes option to true in your next.config.js file. Here's an example configuration:

// next.config.js
const nextConfig = {
  experimental: {
    typedRoutes: true,
  },
};

module.exports = nextConfig;
Enter fullscreen mode Exit fullscreen mode

This feature is still in beta and currently does not support rewrites and redirects. However, it is a significant step towards improving type safety in Next.js applications.

Using nextjs-routes for Typed Routing

While the built-in typed routes feature in Next.js is still experimental, there is a third-party library called nextjs-routes that provides type-safe routing for both the app directory and pages. This library scans your pages directory and generates route types based on your application's routes, ensuring that your links are type-safe with zero runtime overhead.

Installation and Setup

To use nextjs-routes, you need to install the package and update your next.config.js file as follows:

npm install nextjs-routes
# or
yarn add nextjs-routes
# or
pnpm add nextjs-routes
Enter fullscreen mode Exit fullscreen mode

Then, update your next.config.js:

// next.config.js
const nextRoutes = require("nextjs-routes/config");
const withRoutes = nextRoutes();

const nextConfig = {
  reactStrictMode: true,
};

module.exports = withRoutes(nextConfig);
Enter fullscreen mode Exit fullscreen mode

After running npx next dev or npx next build, a @types/nextjs-routes.d.ts file will be generated, which augments the type definitions for next/link and next/router.

Examples of Typed Routing with nextjs-routes

Here are some examples of how you can use typed routing with nextjs-routes:

Link Component

import Link from "next/link";

// Typed href based on your application routes
<Link
  href={{
    pathname: "/posts/[postId]",
    query: { postId: "123" },
  }}
>
  Read Post
</Link>;

// For routes without parameters, you can use a string
<Link href="/about">About Us</Link>;
Enter fullscreen mode Exit fullscreen mode

useRouter Hook

import { useRouter } from "next/router";

const router = useRouter();

// Typed push method
router.push({
  pathname: "/posts/[postId]",
  query: { postId: "456" },
});

// Typed replace method
router.replace("/");

// Typed query object
const { query } = useRouter();
// query is typed as a union of all query parameters defined by your application's routes
Enter fullscreen mode Exit fullscreen mode

getServerSideProps

import type { GetServerSidePropsContext } from "nextjs-routes";

export function getServerSideProps(
  context: GetServerSidePropsContext<"/posts/[postId]">
) {
  // context.params will include `postId` as a string
  const { postId } = context.params;
}
Enter fullscreen mode Exit fullscreen mode

Custom Example: Typed Blog Post Routes

Let's create a custom example to illustrate how typed routes can be used in a practical scenario. Imagine we have a blog application with dynamic routes for individual blog posts. We want to ensure that our links to these posts are type-safe.

First, we define our blog post page under the pages/posts/[postId].tsx file. Then, we use nextjs-routes to generate the typed routes.

// pages/posts/[postId].tsx
import { useRouter } from "next/router";
import Link from "next/link";

const PostPage = () => {
  const router = useRouter();
  const { postId } = router.query as { postId: string };

  return (
    <div>
      <h1>Post {postId}</h1>
      <Link href="/posts">
        <a>Back to posts</a>
      </Link>
    </div>
  );
};

export default PostPage;
Enter fullscreen mode Exit fullscreen mode

Now, when we link to a post, we can use the typed href to ensure that we pass the correct postId:

// pages/posts/index.tsx
import Link from "next/link";

const PostsList = ({ posts }) => {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link
            href={{
              pathname: "/posts/[postId]",
              query: { postId: post.id },
            }}
          >
            {post.title}
          </Link>
        </li>
      ))}
    </ul>
  );
};

export default PostsList;
Enter fullscreen mode Exit fullscreen mode

With nextjs-routes, if we accidentally mistype the route or forget to pass the required postId, TypeScript will alert us at compile time, preventing potential runtime errors.

Conclusion

Typed routes in Next.js provide a robust way to ensure that your application's routing is type-safe, reducing the risk of errors and improving the developer experience. While the built-in typed routes feature in Next.js is still experimental, the nextjs-routes library offers a stable solution that works with both the app directory and pages. By following the examples provided, you can implement typed routes in your Next.js projects and enjoy the benefits of type safety in your routing logic.

Remember to keep an eye on the Next.js documentation and release notes for updates on the typed routes feature as it moves towards stability. Happy coding!

Top comments (0)