Skip to content

Commit

Permalink
add next-naviation type helpers (#196)
Browse files Browse the repository at this point in the history
* add next-naviation type helpers

* Update README.md

* Update README.md

* Update README.md
  • Loading branch information
tatethurston authored Sep 20, 2024
1 parent 71afd45 commit 5484840
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 2 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ If you want a type for all possible `pathname`s you can achieve this via `Route`

```ts
import type { Route } from "nextjs-routes";

// '/' | '/foos/[foo]' | 'other-route' | ...
type Pathname = Route["pathname"];
```

Expand All @@ -192,9 +194,17 @@ type Pathname = Route["pathname"];
If you want to use the generated `Query` for a given `Route`, you can import it from `nextjs-routes`:

```ts
// Query | Query & { foo: string } | ...
import type { RoutedQuery } from "nextjs-routes";
```

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 the path as a type argument:

```ts
// Query & { foo: string }
type FooRouteQuery = RoutedQuery<"/foos/[foo]">;
```

### GetServerSidePropsContext

If you're using `getServerSideProps` consider using `GetServerSidePropsContext` from nextjs-routes. This is nearly identical to `GetServerSidePropsContext` from next, but further narrows types based on nextjs-route's route data.
Expand Down
44 changes: 44 additions & 0 deletions examples/app/@types/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,47 @@ declare module "next/router" {

export function useRouter<P extends Route["pathname"]>(): NextRouter<P>;
}

// prettier-ignore
declare module "next/navigation" {
export * from "next/dist/client/components/navigation";
import type { RoutedQuery, RouteLiteral } from "nextjs-routes";

/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read the current URL's pathname.
*
* @example
* ```ts
* "use client"
* import { usePathname } from 'next/navigation'
*
* export default function Page() {
* const pathname = usePathname() // returns "/dashboard" on /dashboard?foo=bar
* // ...
* }
* ```
*
* Read more: [Next.js Docs: `usePathname`](https://nextjs.org/docs/app/api-reference/functions/use-pathname)
*/
export function usePathname(): RouteLiteral;

/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read a route's dynamic params filled in by the current URL.
*
* @example
* ```ts
* "use client"
* import { useParams } from 'next/navigation'
*
* export default function Page() {
* // on /dashboard/[team] where pathname is /dashboard/nextjs
* const { team } = useParams() // team === "nextjs"
* }
* ```
*
* Read more: [Next.js Docs: `useParams`](https://nextjs.org/docs/app/api-reference/functions/use-params)
*/
export function useParams<Pathname extends Route["pathname"] = Route["pathname"]>(): RoutedQuery<Pathname>;
}
2 changes: 1 addition & 1 deletion packages/nextjs-routes/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nextjs-routes",
"version": "2.2.2-rc.1",
"version": "2.2.2-rc.2",
"description": "Type safe routing for Next.js",
"license": "MIT",
"author": "Tate <[email protected]>",
Expand Down
132 changes: 132 additions & 0 deletions packages/nextjs-routes/src/__snapshots__/core.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,50 @@ declare module "next/router" {
export function useRouter<P extends Route["pathname"]>(): NextRouter<P>;
}
// prettier-ignore
declare module "next/navigation" {
export * from "next/dist/client/components/navigation";
import type { RoutedQuery, RouteLiteral } from "nextjs-routes";
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read the current URL's pathname.
*
* @example
* \`\`\`ts
* "use client"
* import { usePathname } from 'next/navigation'
*
* export default function Page() {
* const pathname = usePathname() // returns "/dashboard" on /dashboard?foo=bar
* // ...
* }
* \`\`\`
*
* Read more: [Next.js Docs: \`usePathname\`](https://nextjs.org/docs/app/api-reference/functions/use-pathname)
*/
export function usePathname(): RouteLiteral;
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read a route's dynamic params filled in by the current URL.
*
* @example
* \`\`\`ts
* "use client"
* import { useParams } from 'next/navigation'
*
* export default function Page() {
* // on /dashboard/[team] where pathname is /dashboard/nextjs
* const { team } = useParams() // team === "nextjs"
* }
* \`\`\`
*
* Read more: [Next.js Docs: \`useParams\`](https://nextjs.org/docs/app/api-reference/functions/use-params)
*/
export function useParams<Pathname extends Route["pathname"] = Route["pathname"]>(): RoutedQuery<Pathname>;
}
",
],
]
Expand Down Expand Up @@ -371,6 +415,50 @@ declare module "next/router" {
export function useRouter<P extends Route["pathname"]>(): NextRouter<P>;
}
// prettier-ignore
declare module "next/navigation" {
export * from "next/dist/client/components/navigation";
import type { RoutedQuery, RouteLiteral } from "nextjs-routes";
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read the current URL's pathname.
*
* @example
* \`\`\`ts
* "use client"
* import { usePathname } from 'next/navigation'
*
* export default function Page() {
* const pathname = usePathname() // returns "/dashboard" on /dashboard?foo=bar
* // ...
* }
* \`\`\`
*
* Read more: [Next.js Docs: \`usePathname\`](https://nextjs.org/docs/app/api-reference/functions/use-pathname)
*/
export function usePathname(): RouteLiteral;
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read a route's dynamic params filled in by the current URL.
*
* @example
* \`\`\`ts
* "use client"
* import { useParams } from 'next/navigation'
*
* export default function Page() {
* // on /dashboard/[team] where pathname is /dashboard/nextjs
* const { team } = useParams() // team === "nextjs"
* }
* \`\`\`
*
* Read more: [Next.js Docs: \`useParams\`](https://nextjs.org/docs/app/api-reference/functions/use-params)
*/
export function useParams<Pathname extends Route["pathname"] = Route["pathname"]>(): RoutedQuery<Pathname>;
}
",
],
]
Expand Down Expand Up @@ -1694,6 +1782,50 @@ declare module "next/router" {
export function useRouter<P extends Route["pathname"]>(): NextRouter<P>;
}
// prettier-ignore
declare module "next/navigation" {
export * from "next/dist/client/components/navigation";
import type { RoutedQuery, RouteLiteral } from "nextjs-routes";
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read the current URL's pathname.
*
* @example
* \`\`\`ts
* "use client"
* import { usePathname } from 'next/navigation'
*
* export default function Page() {
* const pathname = usePathname() // returns "/dashboard" on /dashboard?foo=bar
* // ...
* }
* \`\`\`
*
* Read more: [Next.js Docs: \`usePathname\`](https://nextjs.org/docs/app/api-reference/functions/use-pathname)
*/
export function usePathname(): RouteLiteral;
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read a route's dynamic params filled in by the current URL.
*
* @example
* \`\`\`ts
* "use client"
* import { useParams } from 'next/navigation'
*
* export default function Page() {
* // on /dashboard/[team] where pathname is /dashboard/nextjs
* const { team } = useParams() // team === "nextjs"
* }
* \`\`\`
*
* Read more: [Next.js Docs: \`useParams\`](https://nextjs.org/docs/app/api-reference/functions/use-params)
*/
export function useParams<Pathname extends Route["pathname"] = Route["pathname"]>(): RoutedQuery<Pathname>;
}
",
],
]
Expand Down
52 changes: 51 additions & 1 deletion packages/nextjs-routes/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function generate(routes: Route[], config: GenerateConfig): string {
localeDetection: false,
locales: [],
};
return `\
let output = `\
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
// This file will be automatically regenerated when your Next.js server is running.
// nextjs-routes version: ${pkg.version}
Expand Down Expand Up @@ -313,6 +313,56 @@ declare module "next/router" {
export function useRouter<P extends Route["pathname"]>(): NextRouter<P>;
}
`;

if (config.usingAppDirectory) {
output += `\
// prettier-ignore
declare module "next/navigation" {
export * from "next/dist/client/components/navigation";
import type { RoutedQuery, RouteLiteral } from "nextjs-routes";
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read the current URL's pathname.
*
* @example
* \`\`\`ts
* "use client"
* import { usePathname } from 'next/navigation'
*
* export default function Page() {
* const pathname = usePathname() // returns "/dashboard" on /dashboard?foo=bar
* // ...
* }
* \`\`\`
*
* Read more: [Next.js Docs: \`usePathname\`](https://nextjs.org/docs/app/api-reference/functions/use-pathname)
*/
export function usePathname(): RouteLiteral;
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read a route's dynamic params filled in by the current URL.
*
* @example
* \`\`\`ts
* "use client"
* import { useParams } from 'next/navigation'
*
* export default function Page() {
* // on /dashboard/[team] where pathname is /dashboard/nextjs
* const { team } = useParams() // team === "nextjs"
* }
* \`\`\`
*
* Read more: [Next.js Docs: \`useParams\`](https://nextjs.org/docs/app/api-reference/functions/use-params)
*/
export function useParams<Pathname extends Route["pathname"] = Route["pathname"]>(): RoutedQuery<Pathname>;
}
`;
}
return output;
}

function print(x: unknown, indent: number): string {
Expand Down

0 comments on commit 5484840

Please sign in to comment.