nextjs-routes
nextjs-routes copied to clipboard
Type safe routing for Next.js
Next.js Routes
Type safe routing for Next.js

What is this? 🧐
A code generation tool to make next/link and next/router routes type safe with zero runtime overhead. nextjs-routes scans your pages directory and generates a nextjs-routes.d.ts file with type definitions for all your routes.
Installation & Usage 📦
-
Add this package to your project:
npm install nextjs-routesoryarn add nextjs-routes -
Update your
next.config.js:+ const { withRoutes } = require("nextjs-routes/next-config.cjs"); /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, }; - module.exports = nextConfig; + module.exports = withRoutes(nextConfig);This wiring will only run in Next.js' development server (eg
npx next dev) andwithRouteswill no-op in production. -
Start your next server:
npx next devoryarn next dev
That's it! A nextjs-routes.d.ts file will be generated the first time you start your server. Check this file into version control. next/link and next/router type definitions have been augmented to verify your application's routes. No more broken links, and you get route autocompletion 🙌.
Whenever your routes change, your nextjs-routes.d.ts file will automatically update.
Highlights
🦄 Zero config
💨 Types only -- zero runtime
🛠 No more broken links
🪄 Route autocompletion
🔗 Supports all Next.js route types: static, dynamic, catch all and optional catch all
Examples 🛠
Link
Link's href prop is now typed based on your application routes and expects a URL object:
import Link from "next/link";
function Home() {
return (
<Link
href={{
pathname: "/foos/[foo]",
query: { foo: "test" },
}}
>
<a>About us</a>
</Link>
);
}
export default Home;
useRouter
useRouter's returned router instance types for push, replace and query are now typed based on your application routes.
Identical to Link, push and replace now expect a URL object:
push
import { useRouter } from "next/link";
const router = useRouter();
router.push({ pathname: "/foos/[foo]", query: { foo: "test" } });
replace
import { useRouter } from "next/link";
const router = useRouter();
router.replace({ pathname: "/" });
query
import { useRouter } from "next/link";
// query is typed as a union of all query parameters defined by your application's routes
const { query } = useRouter();
By default, query will be typed as the union of all possible query parameters defined by your application routes. If you'd like to narrow the type to fewer routes or a single page, you can supply a type argument:
import { useRouter } from "next/link";
// query is now typed as `{ foo: string }`
const { query } = useRouter<"/foos/[foo]">();
Route
If you want to use the generated Route type in your code, you can import it from nextjs-routes:
import type { Route } from "nextjs-routes";
How does this work? 🤔
nextjs-routes generates types for the pathname and query for every page in your pages directory. The generated types are written to nextjs-routes.d.ts which is automatically referenced by your Next project's tsconfig.json. nextjs-routes.d.ts redefines the types for next/link and next/router and applies the generated route types.
What if I need a runtime?
There are some cases where you may want to generate a type safe path from a Route object, such as when fetching from an API route or serving redirects from getServerSideProps. These accept strings instead of the Route object that Link and useRouter accept. Because these do not perform the same string interpolation for dynamic routes, runtime code is required instead of a type only solution.
For these cases, you can use route from nextjs-routes:
fetch
import { route } from "nextjs-routes";
fetch(route({ pathname: "/api/foos/[foo]", query: { foo: "foobar" } }));
getServerSideProps
import { route } from "nextjs-routes";
export const getServerSideProps: GetServerSideProps = async (context) => {
return {
redirect: {
destination: route({ pathname: "/foos/[foo]", query: { foo: "foobar" } }),
permanent: false,
},
};
};
Contributing 👫
PR's and issues welcomed! For more guidance check out CONTRIBUTING.md
Licensing 📃
See the project's MIT License.