Next.js Discord

Discord Forum

Dynamic Route Typing

Unanswered
Luke posted this in #help-forum
Open in Discord
Hey all, quick preface: I don't necessarily think this belongs in the help-forum, I would have preferred to put this in #discussions, but I don't have write permissions at the moment.

Here's my question/discussion:

In Next.js, we have dynamic routes, the basic example would be:

// /users/[userId]/page.tsx
export default function UserPage({
  params,
}: {
  params: { userId: string };
}) {}


But, let's say a userId is/should be a number, and not a string. Then I would go ahead and change the params type to:

params: { userId: number }


But, there is an odd caveat, which is that all params come in as strings (unless I'm mistaken), no matter what.

If I type params.userId to be a number, it's actually a string.

This makes sense, as routes are inherently strings, and I don't expect Next to handle the conversion for me, or even worse, make assumptions about the type and perform an automatic conversion.

But, how does this have implications on best practices? If I put number as the type, the code all works, and I get no linting errors.

Am I mistaken in assuming that this is problematic? Should a type exist that allows you to define what the params are but not their types to avoid confusion for users?

34 Replies

Yeah, I guess I'm more concerned with the foot gun of typing a route param as something other than a string
I made a basic type to make my life less stressful for this, and to prevent any accidents across the app for my whole team
declare module "next" {
  type DynamicRouteParams<T extends string> = {
    params: {
      [K in T]: string;
    };
  };
}


Basic usage:
export default
 async function UserPage({
  params,
}: DynamicRouteParams<"userId">) {


I am personally of the opinion that a type like this should be exposed by default from next to prevent any misuse and incorrect typing.
Web urls are all string based.
When you type your localhost/users/2 in a browser tab you enter it as string.
Next is only giving you the string value of your dynamic route!

If but you can override the type by using Number function
@ItetsuLaTable Web urls are all string based. When you type your localhost/users/2 in a browser tab you enter it as string. Next is only giving you the string value of your dynamic route! If but you can override the type by using Number function
Definitely get that, my concern really lies with the fact that you can just freely type the incoming params as whatever you'd like with no errors on linting, etc
I got your point to have a number instead of string but that the only case
You cannot type it as custom type or array
@ItetsuLaTable I'd argue it's not, you could type a route param as a union like

params: { type: "test" | "hello" }

While in reality, that quote param could be anything
Well for the DX that a cool stuff to have for sure!
Yeah, i don't think it's a huge deal, I'm definitely making more of it than it really is
But would be really nice if Next provided some typing / additional docs on that
Yes but if you type it as union whats going on if you enter toto instead of test or hello? Is that a 404 or 500 ?
now I'm curious
let me try
Because ts wont be happy because it does not match
Yeah, this is exactly what I'm concerned with:

// test/[testParam]/page.tsx

export default async function TestPage({
  params,
}: {
  params: { testParam: "foo" | "bar" };
}) {
  console.log(params);

  return <h1>{JSON.stringify(params)}</h1>;
}
Here is a very basic example
And in a perfect world, you'd think that testParams is either foo or bar, and other things would cause errors, etc
But that's not the case, testParam works no matter what I set it to on the route
It's prime for runtime errors, and the next docs mention nothing about that
Even just a simple "All params come in as a string, there is no enforcement of the types that you may set" would be such a good thing for them to note
I guess its due to typing isnot supported here
Yeah, I mean I totally get why they all come in as strings
I just don't think that Next should then allow you to type them as whatever you'd hypothetically like
I agree! I dont think Next should allow us to do it or we’ll found many issues
❤️ I'm glad I'm not alone
I think it's especially a problem on larger teams
If I have 12 people on my team, I can't expect all of them to know that params come in as indiscriminate strings
I just extended the next module (which I usually discourage) and added a "DynamicRouteParams" type that allows you to say the name of the route params, but no types, it will just set them to string (to match nextjs behavior)
like this:

new type
declare module "next" {
  type DynamicRouteParams<T extends string> = {
    params: {
      [K in T]: string;
    };
  };
}

Basic usage:
export default
 async function UserPage({
  params,
}: DynamicRouteParams<"userId">) {
You just need to remember that it is always string and not numbers or union of literal strings or whatever you can come up with. So you need to specify it as string and handle the conversion to the format you like manually.
Also, pretty sure that if you put number or string union or anything that is wrong in there, the build will fail because next does check the function signature there.