Replies: 5 comments 1 reply
-
This would be a big improvement for me. I've put quite a bit of effort into making my next routing as type safe as possible, but I can only take it so far. Now that TanStack Router is out, I'm once again reminded of how nice type-safe routing is and I want it :) Here's some thoughts on part 3: With the new route builder, the generic could at least be optional, which would be significantly more ergonomic: I do think the syntax could be a bit more consistent between the three options though. My favorite is the syntax on the 3.3 (link component), although the syntax in 3.1 could work as well. Not a big dealbreaker though. We should probably also update types of here's what that would look like in my mind, by the wayApp Router using the same syntax as Link: // /my-app/src/app/some-page/page.tsx
import type { FC } from 'react'
import { AppDir } from '~/lib'
const AppComponent: FC = () => {
const appRouter = AppDir.useRouter()
appRouter.push({
route: '/todos',
query: { hello: 'world' },
hash: 'foo',
})
return null
}
export default AppComponent Pages Router using the same syntax as Link: // /my-app/src/pages/some-page.tsx
'use client'
import type { FC } from 'react'
import { PagesDir } from '~/lib'
const PagesComponent: FC = () => {
const pagesRouter = PagesDir.useRouter()
/// Example with static path
pagesRouter.push({
route: '/todos',
})
/// Example with dynamic path
// TypeScript warns about the missing 'id' parameter
// @ts-expect-error
pagesRouter.push({
route: '/todos/[id]',
})
pagesRouter.push({
route: '/todos/[id]',
params: { id: 'hi' },
})
return null
}
export default PagesComponent And redirect, using the same type: // /my-app/src/app/hello-world/page.tsx
export default async function MyPage() {
const session = await auth()
if (!session) {
redirect({
route: "/login",
query: { then: "/hello-world" },
})
}
return "hello world"
} As for part 4, there's already syntax for defining searchParams that we can draw from: export default function MyPage({
searchParams: { hello },
}: {
searchParams: { hello?: string; page: number }
}) {
return null
} The syntax is already there, so might as well use it. Ideally, there would be some processing and validation to support types like number or Record, but that might be a bit out of scope for these changes. |
Beta Was this translation helpful? Give feedback.
-
Build something similar for my use case, the current |
Beta Was this translation helpful? Give feedback.
-
Can some one help with this one? #63779 |
Beta Was this translation helpful? Give feedback.
-
I'm really liking this proposal! This is exactly the direction I'd like to see typed routes go, the sooner the better. I'd like to push back a little on To go along with extending Next's route segment config, we could have the types provided by import { PageProps } from "next"; // i made this up, but it would be nice
import { z } from "zod";
export const PARAMS = z.object({
id: z.coerce.number()
});
export const QUERY = z.object({
hello: z.string(),
filters: z.array(z.string()).optional()
});
export default function MyPage({
params, // typed as { id: number; }
query // typed as { hello: string; filters?: Array<string>; }
}: PageProps<z.infer<typeof PARAMS>, z.infer<typeof QUERY>>) { // or perhaps PageProps<typeof PARAMS, typeof QUERY>
return null;
}
This is cool and I want it, but I wouldn't expect Edit: clarify error handling |
Beta Was this translation helpful? Give feedback.
-
Thank you awesome extension. I would like to use with |
Beta Was this translation helpful? Give feedback.
-
Goals
Enhancing the router types via the
typedRoutes
experimental feature.As an outsider it feels like routing types have been on back burner for
next.js
.In a large project with a lot of routes it is easy to forget what (query) parameters a URL needs.
typedRoutes
feels like a good start but it could be much more extensible.The current implementation mainly focuses on manually creating string literals.
Here are the main goals:
next.js
primitivesAuthor's note
I am more than willing to open a PR and implement these changes myself. I realise the next.js dev team is busy enough as is.
Background
Internal
This is meant to extend the work that @shuding has already done.
The webpack plugin's source code can be found at /packages/next/src/build/webpack/plugins/next-types-plugin.
If the feature is enabled, the plugin generates this file:
Third-party
There exists a next-type-safe-routes package.
The last update is from 1 year ago and it does not support
app
dir.This probably was created before the
typedRoutes
experimental feature was released.Related discussions
'Expose typedRoutes route builder function' proposes a route builder function to be included by
next.js
.This is only a small part of my proposal and third party libraries could easilly accomplish this is the first part of my proposal would be implemented.
Proposal
I've created a mock PR in my fork, so you can easily see the code changes.
I would gladly contribute myself.
In this discussion I'll outline some ideas and would love to hear your feedback on them.
General
I've added a temporary
PoC_Routes
namespace that gets generated at compile time.This namespace is used distinguish shudding's and my types from each other.
All proof of concept code can be found in
/dev/app/{lib, examples}
.I'm well aware there are some caveats to my code. Some examples:
'/users/[id]/todos/[id]'
) are not supported.I've written code for proposals 1..=3. The 4th proposal mainly lives in my head right now because I'm not sure if it's the right way to implement it.
1. Separate app and pages route raw types
I've adjust the webpack plugin to also generate the following code:
typedRoutes
currently does not distinguish betweenapp
andpages
routes.It would be handy to separate them for library developers creating router wrappers (e.g. solito)
2. A function to create type safe routes
This would further the 'Expose typedRoutes route builder function' feature request.
If the first proposal were to be implemented, library authors could make this function easily but I like the idea of this being standardized by
next.js
itself.Here my implementation in action: (source code can be found here)
3. Router type enhancements
This would require some changes to the router source code so this probably won't get implemented.
Still, this could be third-party library by some external developer.
Source code:
I've enhanced the following
next.js
primitives to use thecreateUrl
function.3.1 Pages router
The pages router already takes in
string | URL
as its first parameter.I've added the data needed for
createUrl
as a valid optionPagesDir source code
3.2 App router
AppDir source code
3.3 Link
Link source code
4. Typed query parameters
It would be very handy if we could define the query parameters for a given route.
Something like route segment config comes to mind.
An example:
This could be parsed into the
PoC_Routes
definitions5. Exporting routes as javascript arrays
This is optional but I can't think of a reason why not to.
It isn't supported right now because the types are generated in
types.d.ts
, which usesdeclare module
magic to override types.It could, however, be useful to some library author to access these. There would be next to no build performance penalty, because most of the needed work is already there.
Example use case:
I have written a dev overlay that uses a route map, generated by a Rust CLI to quickly navigate between pages without the need of a navbar. If this was freely available, I wouldn't have needed to write the Rust CLI.
Some example generated output:
Beta Was this translation helpful? Give feedback.
All reactions