Next.js Discord

Discord Forum

dynamic route param type mismatch

Unanswered
Tundra Swan posted this in #help-forum
Open in Discord
Tundra SwanOP
Say I have a route handler at my-app/app/api/[resourceId]/route.ts with something like this:

type Params = Promise<{ resourceId: Resource["id"] }>
export async function PATCH(request: NextRequest, ctx: { params: Params }) {
    [...]
}


where Resource["id"] is a branded type: string & BRAND<"ResourceId">

This used to compile just fine in next 15.4. I have, however, recently upgraded to 15.5 and this no longer compiles when running next build:

Type '{ params: Promise<{ resourceId: string; }>; }' is not assignable to type '{ params: Promise<{ resourceId: string & BRAND<"ResourceId">; }>; }'.


Is this expected behaviour in 15.5? Is there any way to opt out of this or otherwise get the 15.4 behaviour without actually downgrading?

17 Replies

Tundra SwanOP
it's a branded type

think of it like this:

type Brand<K, T> = K & { __brand: T }
type ResourceId = Brand<string, "ResourceId ">


the idea behind branded types is to distinguish between structurally identical types at the type level

https://egghead.io/blog/using-branded-types-in-typescript
like what is it defined as in your code
Brand requires 2 generic types but yours only used one
sorry im having trouble understanding with the problem
Tundra SwanOP
it's a type helper from zod which basically does the same

ultimately, the problem is that i'm passing the branded type to the route handler param but next 15.5 expects a simple string in its autogenerated route typings

at least that's what i gather from the error msg:

Type '{ params: Promise<{ resourceId: string; }>; }' is not assignable to type '{ params: Promise<{ resourceId: string & BRAND<"ResourceId">; }>; }'.
so.. BRAND<"ResourceId"> is { __brand: "ResourceId" } ?
im not sure why you need to modify the type of the route handler param differently as doing string & { __brand: "ResourceId" } is different than just string
next will throw a type error since it is incompatible
Tundra SwanOP
well that's the point, it hasn't up until 15.5
have you tried adding //@ts-ignore above it
i dont think theres specific config to disable this specific feature as these strict type checks are designed to make dev safer
there is this
moreover, i dont think you should be branding params if im reading the article right
Tundra SwanOP
yeah, i'd rather not lose all safety here

i do understand the issue, my only real gripe is that it seems to be a breaking change introduced in a minor version

this worked fine in 15.4
the change must have been introduced in 15.5

i also have some ideas on how to work around it... i could refactor the params to be non-branded types and then validate them inside the handlers... but i've got tons and tons of these already and i wanted to avoid doing this "by hand" (i mean, i would get some AI to do it but it would still have to be double checked)
i could refactor the params to be non-branded types and then validate them inside the handlers...
i would definetly do that since the params are unsafe parameters and is best practice to be treated with caution